2013-11-04 45 views
3

我是新來查詢優化,所以我接受我不明白的一切,但我不明白爲什麼即使這個簡單的查詢沒有按預期優化。MySql拒絕使用索引

我的表:

+------------------+-----------+------+-----+-------------------+----------------+ 
| Field   | Type  | Null | Key | Default   | Extra   | 
+------------------+-----------+------+-----+-------------------+----------------+ 
| tasktransitionid | int(11) | NO | PRI | NULL    | auto_increment | 
| taskid   | int(11) | NO | MUL | NULL    |    | 
| transitiondate | timestamp | NO | MUL | CURRENT_TIMESTAMP |    | 
+------------------+-----------+------+-----+-------------------+----------------+ 

我的指標:

+-----------------+------------+-------------------+--------------+------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
| Table   | Non_unique | Key_name   | Seq_in_index | Column_name  | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | 
+-----------------+------------+-------------------+--------------+------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
| tasktransitions |   0 | PRIMARY   |   1 | tasktransitionid | A   |   952 |  NULL | NULL |  | BTREE  |   |    | 
| tasktransitions |   1 | transitiondate_ix |   1 | transitiondate | A   |   952 |  NULL | NULL |  | BTREE  |   |    | 
+-----------------+------------+-------------------+--------------+------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 

我的查詢:

SELECT taskid FROM tasktransitions WHERE transitiondate>'2013-09-31 00:00:00'; 

給出了這樣的:

+----+-------------+-----------------+------+-------------------+------+---------+------+------+-------------+ 
| id | select_type | table   | type | possible_keys  | key | key_len | ref | rows | Extra  | 
+----+-------------+-----------------+------+-------------------+------+---------+------+------+-------------+ 
| 1 | SIMPLE  | tasktransitions | ALL | transitiondate_ix | NULL | NULL | NULL | 1082 | Using where | 
+----+-------------+-----------------+------+-------------------+------+---------+------+------+-------------+ 

如果我理解正確,Using whereALL表示所有行都從存儲引擎中檢索並在服務器層進行過濾。這是次優的。爲什麼它拒絕使用索引,只能從存儲引擎(innoDB)中檢索請求的範圍?

乾杯

+0

你試過強迫索引了嗎? – Kermit

+0

@FreshPrinceOfSO不,但我爲什麼要?我希望預處理器足夠聰明,給定高基數以自動選擇索引。 – Tin

+0

可能因爲索引是無用的。 – Kermit

回答

3

的MySQL,如果它估計,它會選擇表的顯著很大一部分,而且它認爲表掃描實際上在這些情況下更有效的是不會使用索引。

通過類比,這是一本書的索引不包含像「the」這樣非常常見的詞的原因 - 因爲如果在索引中查找單詞並查找列表頁碼是一個很長的名單,甚至書中的每一頁。簡單地閱讀書籍封面將會更有效率。

我的經驗是,如果查詢的搜索條件匹配大於表的20%,並且這通常是正確的交叉點,那麼這發生在MySQL中。根據數據類型,表格大小等可能會有一些變化。

您可以給MySQL一個提示,說服它表掃描會過於昂貴,所以它會更有可能使用該指數。這通常不是必需的,但你可以這樣做:

SELECT taskid FROM tasktransitions FORCE INDEX (transitiondate_ix) 
WHERE transitiondate>'2013-09-31 00:00:00'; 
+0

謝謝@Bill,這似乎確實是原因。查詢返回987行中的186行。當我改變日期,只有10行匹配時,它使用索引。我仍然不明白的是,當使用密鑰時,使用where'是解釋的輸出。 – Tin

+0

'使用where'只是表示SQL執行正在應用一個條件來過濾掉一些行。換句話說,並不是所有被檢查的行都被返回。 –

+0

我正在讀Baron Schwartz的高性能MySql一書。根據這本書「使用where」意味着從存儲引擎讀取的行太多,更好的索引可能會解決這個問題。但我不明白如何。 – Tin