2009-12-09 57 views
2

我有一个查询,我正在通过一些字段排列联盟表来处理结果中某些字段可能具有相同值的情况。我很好奇,为什么当后续字段不需要进行二级排序时,查询仍然相当慢。mySQL ORDER优化

典型案例是一张投票表格。 它包含一个total字段,该字段是一个缓存值votes_up减去votes_down。当查询排行榜(如排名前10)时,如果两个总数相等,则按votes_up订购。最后,如果两者都相同,则可以使用其他字段,例如主键。

下面是一个例子表:

CREATE TABLE `items` (
    `id` int unsigned NOT NULL, 
    `votes_up` mediumint NOT NULL, 
    `votes_down` mediumint NOT NULL, 
    `total` mediumint NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `votes_up` (`votes_up`), 
    KEY `total` (`total`) 
) 

一个基本的前十名查询与订购的一个领域是快如闪电;例如:

SELECT * FROM `items` ORDER BY `total` DESC LIMIT 10; 
(0.00 secs) 

添加用于二级排序的votes_up字段会显着减慢它;例如:

SELECT * FROM `items` ORDER BY `total` DESC, `votes_up` DESC LIMIT 10; 
(0.15 secs) 

添加第三个,即使是主键也会进一步降低速度;例如: -

SELECT * FROM `items` ORDER BY `total` DESC, `votes_up` DESC, `id` DESC LIMIT 10; 
(0.18 secs) 

有什么办法来优化这个查询,以便当total字段值都是独一无二的,二次排序的条款将被忽略,不承担那么多的开销?

回答

5

多列索引可能会加快速度。你可以创建一个'total'和'votes_up'的索引。添加'id'将不会执行任何操作,因为这将始终是唯一的。

对于多列索引,请始终将它们与您用于排序的顺序保持一致。

+0

非常棒。那工作的一种享受。 除了我还必须添加主键。没有在密钥中的'id'只在前两个字段上排序得到改进,将第三个添加到较慢的查询中。 所有这三个是闪电: ALTER TABLE' items' ADD INDEX' leaderboard'('total','votes_up','id') 谢谢! – 2009-12-09 22:39:31

+0

啊,太好了!我想知道为什么你在第三次选择时使用了id,因为它始终是唯一的(作为主键)。看起来像它将与第二个查询相同。 – jonstjohn 2009-12-09 22:42:38

0

您可以选择您的结果到一个临时表中,并从那里确定“总计”列的唯一性并相应地管理任何子订单。或者,您可以将主要查询(按“总计”排序)放入视图中,并仅对其应用二级排序;这应该会加快它的速度。

+0

谢谢,尽管最初的10行可能不是正确的,所以排序它们将毫无意义。即真正的#10可能在#12,所以不在初始集合 – 2009-12-09 22:41:27

+0

嗯,我并不特别期待在视图中的限制,但是,我明白你的观点。无论如何,多列索引的其他答案显然是要走的路... – 2009-12-09 23:48:36