2016-11-10 62 views
0

我有一個innodb表,表中的查詢如下所示。由於錯誤的行估計,MySQL Innodb無法使用索引

SELECT * 
FROM x 
WHERE now() BETWEEN a AND b 

我已經創建的複合指數(A,B)中,查詢返回周圍4K行,而行的表中的總數約爲700K。

但是,當我得到EXPLAIN的執行計劃時,我發現查詢沒有使用預期的索引。因爲估計的rows大約是360k,比實際值大得多。

我知道就像很多帖子(如Why the rows returns by "explain" is not equal to count()?)已經解釋過,EXPLAIN只能粗略估計。但FORCE INDEX解決方案非常棘手,未來可能會帶來潛在的性能風險。

有沒有什麼辦法可以讓MySQL獲得更準確的估計(目前的估計是90倍)?謝謝。

+0

不,它無法使用索引,因爲索引是無用的。掃描表格更有效。 –

回答

0

InnoDB只保留表的近似行數。這是SHOW TABLE STATUS文檔中解釋說:

的行數。一些存儲引擎(如MyISAM)存儲確切的計數。對於其他存儲引擎,如InnoDB,這個值是一個近似值,可能會與實際值相差40%到50%。

我不認爲有什麼辦法可以讓InnoDB保持準確的行數,但它不是如何工作。

+0

感謝您的回覆。所以如果我們不把表拆分成小表,加快查詢的唯一方法是'FORCE INDEX'?我擔心的是,當數據分佈發生變化或未來指數發生變化時,我們可能不會意識到'FORCE INDEX'的影響。手動選擇索引太棘手。 – twds

+0

我還沒有真正研究它,所以我不能回答這個問題。 – Barmar

+0

我的猜測是他們確定對查詢優化的影響不夠大,不足以要求他們解決保持精確計數的問題。 – Barmar

0

這種特殊的結構是難以優化:

WHERE constant BETWEEN col1 AND col2 

沒有mysql指標可以設計,使其運行速度快。這些嘗試包括:

INDEX(col1) -- will scan last half of table 
INDEX(col2) -- will scan first half of table 
INDEX(col1, col2) -- will scan last half of table 

(無論它做更多的工作在B樹取決於ICP,覆蓋等,但在任何情況下,指數,大量的行必須被觸摸)

一原因是無法改進,因爲'半'中的'最後'一行可能實際上匹配。

如果(col1,col2)對不重疊,則可以通過在一行之後停止來提高性能。但MySQL不知道你是否有這種情況,所以它不能優化。 Here是非重疊的的方法有效的IP地址查找。