在日常開發中,使用到的數據表經常都會有索引,這些索引可能是開發人員/DBA建表時創建的,也可能是在使用過程中新增的。合理的使用索引,可以加快數據庫查詢速度。然而,在實際開發工作中,會出現有些sql語句執行時不會使用索引、而使用了全表掃描的情況,造成執行速度慢的問題。下面我列舉兩種比較典型的場景:
場景一:mysql時間字段上使用like
表結構:
CREATE TABLE `orders` (
`orders_id` int(11) NOT NULL,
`order_status` tinyint(4) NOT NULL,
`date_purchased` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`orders_id`),
KEY `idx_date_purchased` (`date_purchased`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
原始語句:
注意到此sql只返回一條結果集,但是有like,把時間字段當成字符串處理了,就做了隱式轉換,故沒法走索引,而是走了全表掃描。
修改后的sql:
場景二:字段本身是字符類型,但是where 條件后卻用整形(沒有加引號)。
為了避免上述問題,除了日常開發中多加小心外,還可以通過explain來檢查sql是否使用索引。方法如下:
(1) 登錄Linux服務器mysql環境(注意不要使用windows本機環境的mysql進行測試,因為測試發現windows mysql下explain檢查結果和linux mysql有不一致的情況)
(2) 將mybatis resource文件中的sql語句中的變量填寫成具體值,並在sql語句前加explain執行,如下:
explain執行結果關注以下幾個字段:
type:
顯示sql執行的類型,從最好到最差的類型為system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL。一般來說,type至少要達到range級別,最好達到ref級別,低於range級別的sql必須進行優化。
key:
顯示sql執行過程中實際使用的鍵或索引,如果為null則表示未使用任何索引,必須進行優化。
Extra:
如果是Only index,這意味着信息只用索引樹中的信息檢索出的,這比掃描整個表要快。
如果是where used,就是使用上了where限制。
如果是impossible where 表示用不着where,一般就是沒查出來啥。
如果此信息顯示Using filesort或者Using temporary的話會很吃力,WHERE和ORDER BY的索引經常無法兼顧,如果按照WHERE來確定索引,那么在ORDER BY時,就必然會引起Using filesort,這就要看是先過濾再排序划算,還是先排序再過濾划算。