MySQL ORDER BY在多对多表中进行优化

时间:2010-09-27 14:25:49

标签: mysql query-optimization

表:

CREATE TABLE IF NOT EXISTS `posts` (

  `post_n` int(10) NOT NULL auto_increment,
  `id` int(10) default NULL,
  `date` datetime NOT NULL default '0000-00-00 00:00:00',

  PRIMARY KEY  (`post_n`,`visibility`),
  KEY `id` (`id`),
  KEY `date` (`date`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

CREATE TABLE IF NOT EXISTS `subscriptions` (

  `subscription_n` int(10) NOT NULL auto_increment,
  `id` int(10) NOT NULL,
  `subscribe_id` int(10) NOT NULL,

  PRIMARY KEY  (`subscription_n`),
  KEY `id` (`id`),
  KEY `subscribe_id` (`subscribe_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

查询:

SELECT posts.* FROM posts, subscriptions 

WHERE posts.id=subscriptions.subscribe_id AND subscriptions.id=1 

ORDER BY date DESC LIMIT 0, 15

它很慢,因为使用索引“id”,“subscribe_id”而不是索引“date”,因此排序非常慢。

是否有任何选项可以更改查询,索引和架构?

2 个答案:

答案 0 :(得分:1)

可能的改进:

首先,如果您为字段命名而不是使用SELECT帖子,则每个查询将获得几微秒。*会导致架构查找。将您的查询更改为:

SELECT posts.post_n, posts.id, posts.date 
FROM posts, subscriptions 
WHERE posts.id=subscriptions.subscribe_id 
  AND subscriptions.id=1 
ORDER BY date DESC 
LIMIT 0, 15

接下来,这需要MySQL 5.1或更高版本,但您可能需要考虑对表进行分区。您可以考虑两个表的KEY分区。

这应该让你开始。 http://dev.mysql.com/doc/refman/5.1/en/partitioning-types.html

E.g。

SET SQL_MODE = 'ANSI';
-- to allow default date
CREATE TABLE IF NOT EXISTS `posts` (
  `post_n` int(10) NOT NULL auto_increment,
  `id` int(10) default NULL,
  `date` datetime NOT NULL default '0000-00-00 00:00:00',
  PRIMARY KEY  (`post_n`,`id`),
  KEY `id` (`id`),
  KEY `date` (`date`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_bin
PARTITION BY KEY(id) PARTITIONS 32;
--
CREATE TABLE IF NOT EXISTS `subscriptions` (
  `subscription_n` int(10) NOT NULL auto_increment,
  `id` int(10) NOT NULL,
  `subscribe_id` int(10) NOT NULL,
  PRIMARY KEY  (`subscription_n`,`subscribe_id`),
  KEY `id` (`id`),
  KEY `subscribe_id` (`subscribe_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_bin
PARTITION BY KEY(subscribe_id) PARTITIONS 32;

我不得不稍微调整你的主键。所以,请注意,这可能不适合您。请测试并确认。我希望,尽管如此。确保对旧的和新的结构/查询运行sysbench,以便在开始生产之前比较结果。 : - )

答案 1 :(得分:0)

如果您能够修改表格,则可以添加包含ID和日期的多字段索引。 (或修改其中一个现有密钥以包含它们)。

如果您无法对数据库进行更改,并且您知道结果集很小,则可以强制它使用USE KEY(name)的特定命名密钥。然后在事实之后完成排序,就在返回的reslts上。

希望有所帮助。