2009-12-09 58 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