1. 程式人生 > >避免寫出不走索引的SQL, MySQL

避免寫出不走索引的SQL, MySQL

故,如果需要計算,千萬不要計算到索引列,想方設法讓其計算到表示式的另一邊去。


索引列使用了函式


同樣的道理,索引列使用了函式,一樣會導致相同的後果


SELECT `sname` FROM `stu` WHERE concat(`sname`,'abc') ='Jaskeyabc'; -- 不會使用索引,因為使用了函式運算,原理與上面相同
SELECT `sname` FROM `stu` WHERE `sname` =concat('Jaskey','abc'); -- 會使用索引
索引列使用了Like %XXX


SELECT * FROM `houdunwang` WHERE `uname` LIKE '字首就走索引%' -- 走索引
SELECT * FROM `houdunwang` WHERE `uname` LIKE '字尾不走索引%' -- 不走索引
所以當需要搜尋email列中.com結尾的字串而email上希望走索引時候,可以考慮資料庫儲存一個反向的內容reverse_email


SELECT * FROM `table` WHERE `reverse_email` LIKE REVERSE('%.com'); -- 走索引
注:以上如果你使用REVERSE(email) = REVERSE('%.com'),一樣得不到你想要的結果,因為你在索引列email列上使用了函式,MySQL不會使用該列索引


同樣的,索引列上使用正則表示式也不會走索引。


字串列與數字直接比較


這是一個坑,假設有一張表,裡面的a列是一個字元char型別,且a上建立了索引,你用它與數字型別做比較判斷的話:


 CREATE TABLE `t1` (`a` char(10));


 SELECT * FROM `t1` WHERE `a`='1' -- 走索引
 SELECT * FROM `t2` WHERE `a`=1 -- 字串和數字比較,不走索引!
但是如果那個表那個列是一個數字型別,拿來和字元型別的做比較,則不會影響到使用索引


 CREATE TABLE `t2` (`b` int);


 SELECT * FROM `t2` WHERE `b`='1' -- 雖然b是數字型別,和'1'比較依然走索引
但是,無論如何,這種額外的隱式型別轉換都是開銷,而且由於有字元和數字比就不走索引的情況,故建議避免一切隱式型別轉換


儘量避免 OR 操作


select * from dept where dname='jaskey' or loc='bj' or deptno=45 --如果條件中有or,即使其中有條件帶索引也不會使用。換言之,就是要求使用的所有欄位,都必須建立索引
所以除非每個列都建立了索引,否則不建議使用OR,在多列OR中,可以考慮用UNION 替換


select * from dept where dname='jaskey' union
select * from dept where loc='bj' union
select * from dept where deptno=45