我有一个查询,其中我通过多个字段排序联盟表来处理结果中某些字段可能具有相同值的情况。我很好奇为什么当次要排序不需要后续字段时,查询仍然慢得多。
一个例子是投票的项目表。
它包含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`)
)
在一个字段上排序的基本十大查询是快速的; e.g:
SELECT * FROM `items` ORDER BY `total` DESC LIMIT 10;
(0.00 secs)
为次要排序添加votes_up字段会大大减慢它的速度; e.g:
SELECT * FROM `items` ORDER BY `total` DESC, `votes_up` DESC LIMIT 10;
(0.15 secs)
添加第三个,即使是主键也会进一步降低速度; e.g:
SELECT * FROM `items` ORDER BY `total` DESC, `votes_up` DESC, `id` DESC LIMIT 10;
(0.18 secs)
有没有办法优化这个查询,以便当total
字段值都是唯一的时候,二级排序子句被忽略并且不会产生这么多开销?
答案 0 :(得分:5)
多列索引可能会加快这一速度。您可以在'total'和'votes_up'上创建索引。添加'id'将不会执行任何操作,因为它始终是唯一的。
使用多列索引时,请始终保持它们与您订购时使用的顺序相同。
答案 1 :(得分:0)
您可以将结果选择到临时表中,然后从中确定“总计”列的唯一性并相应地管理任何子订单。或者,您可以将主查询(按'总计'排序)放入View中,并仅对其应用二级排序;这应该会加速它。