2009-07-17 88 views
7

我有一個基於3列的複合索引,其中兩個約束在我的查詢中,第三個約束在子句中,但mysql不使用索引進行排序。優化我的mysql查詢以使用索引進行排序

 
explain select * from videos where public_private='public' and approved='yes' order by number_of_views desc; 

+----+-------------+--------+------+--------------------------------+------+---------+------+---------+-----------------------------+ 
| id | select_type | table | type | possible_keys     | key | key_len | ref | rows | Extra  | 
+----+-------------+--------+------+--------------------------------+------+---------+------+---------+-----------------------------+ 
| 1 | SIMPLE  | videos | ALL | approved,approved_3,approved_2 | NULL | NULL | NULL | 1476818 | Using where; Using filesort | 
+----+-------------+--------+------+--------------------------------+------+---------+------+---------+-----------------------------+ 

表結構如下:

CREATE TABLE `videos` (
    `indexer` int(9) NOT NULL auto_increment, 
    `user_id` int(9) default NULL, 
    `public_private` varchar(24) default NULL, 
    `approved` varchar(24) default NULL, 
    `number_of_views` int(9) default NULL, 
    PRIMARY KEY (`indexer`), 
    KEY `approved` (`approved`,`user_id`), 
    KEY `approved_3` (`approved`,`public_private`,`indexer`), 
    KEY `approved_2` (`approved`,`public_private`,`number_of_views`), 
) ENGINE=MyISAM AUTO_INCREMENT=1969091 DEFAULT CHARSET=utf8 | 

我應該怎麼做來強制MySQL使用索引排序的結果?

回答

13

我相信你有查詢可能匹配的有很大比例是特別關鍵數據在表中。在這種情況下,MySQL優化器經常選擇進行表掃描並完全忽略索引,因爲它實際上比通過額外讀取整個索引並使用它來挑選數據的麻煩要快。所以在這種情況下,我猜測public_private='yes' and approved='yes'與您的表的很大一部分相匹配。因此,如果MySQL因此而跳過索引,那麼它也不可用於排序。

如果你真的希望它使用一個索引,那麼解決辦法是使用FORCE INDEX

select * from videos FORCE INDEX (approved_2) where public_private='public' and approved='yes' order by number_of_views desc; 

不過,我會運行一些測試,以確保什麼你得到實際上比更快MySQL優化器選擇做什麼。顯然,優化程序does have some issues可以爲訂購做出選擇,所以您可以肯定地給出這一步,看看您是否獲得了改進的性能。

+0

FORCE INDEX解決了問題。現在查詢執行速度快得多,而且您對查詢匹配大部分數據庫是正確的。 – 2009-07-18 11:02:47

+0

好東西,很高興它的工作。 – zombat 2009-07-18 16:36:20

-2

訂單在組合鍵中很重要。我忘記規則,但嘗試以不同的順序。

-2

number_of_views列中添加單獨的索引,然後查看它是否有效。

如果鍵是3列的組合,它將使用,只有當它使用所有3執行操作

+0

編號正確的是:如果一個鍵是3列的組合,當它使用第一列或前兩列或所有三列的組合時,將使用該特定鍵 – 2017-01-12 09:14:54

1

該命令在組合鍵中很重要。如果你想通過剛纔number_of_views使用approved_2鍵,更改排序:

KEY `approved_2` (`approved`,`public_private`,`number_of_views`) 

到:

KEY `approved_2` (`number_of_views`,`approved`,`public_private`) 

左到右MySQL的工作組合鍵。在上面的例子中,重點用number_of_viewsapproved申報,並public_private含蓄上創建索引:

  • number_of_views
  • number_of_viewsapproved
  • number_of_viewsapprovedpublic_private
+0

這個解決方案只會剝奪MySQL的可能性來過濾前兩個字段並對第三個字段進行排序。 – Quassnoi 2009-07-17 18:20:41

0

這應該工作:

`select * from videos where approved='yes' and public_private='public' order by number_of_views desc;` 

如果沒有,只需在number_of_views上創建一個單獨的索引。

這必須工作。

(MySQL的如下左向右的順序基本上是這樣。所以你對approved指數,public_privatenumber_of_views不會,如果不在這個序列中使用工作。也就是說,你可以使用從左邊三個左,2個或最左邊的1 。但是如果你不使用最左邊的那個,這是不行的,這就是主意。)

使用一個單獨的索引會自動排序number_of_views,這可能有助於order by - 我確信這一點。