今天寫了一個統(tǒng)計sql哎媚,在一個近億條數(shù)據(jù)的表上執(zhí)行喇伯,200s都查不出結(jié)果。SQL如下:
select customer,count(1) c
from upv_1
where created between "2015-07-06" and "2015-07-07"
group by customer
having c > 20
order by c desc
執(zhí)行explain,發(fā)現(xiàn)這個sql掃描了8000W條記錄到磁盤上拨与。然后再進行篩選稻据。type=index說明整個索引樹都被掃描了,效果顯然不理想买喧。
拿著這個SQL去請教項目組的數(shù)據(jù)庫大牛捻悯,僅僅加了一個force index,花了1s多就出結(jié)果了岗喉。修改后的SQL如下:
select customer,count(1) c
from upv_1 force index(idx_created)
where created between "2015-07-06" and "2015-07-07"
group by customer
having c > 15
order by c desc
同樣執(zhí)行以下explain命令秋度,這個SQL僅僅掃描了磁盤的110W行記錄。也就是上一個SQL的80分之一钱床。大家都知道荚斯,掃描磁盤是很耗時的IO操作,比內(nèi)存操作慢幾個數(shù)量級。type=range,說明索引樹僅僅被部分掃描事期,要優(yōu)于前面那個SQL.
除了磁盤掃描的行數(shù)的不一樣滥壕,還有采用的索引的不同,上面的sql用的是聯(lián)合索引兽泣,而下面的是單純的created字段的索引绎橘。由于用的是created的索引,驅(qū)動條件就是created的區(qū)間唠倦,需要掃描的數(shù)據(jù)就立刻變小了称鳞,因為時間區(qū)間小。后面的SQL的key_len要遠遠小于前面的SQL稠鼻,也就意味著要掃描的磁盤上的索引數(shù)據(jù)量要遠遠小于前面的SQL冈止。
第一個sql使用的是錯誤的索引,帶來低效的查詢候齿。然后每條SQL只可能使用一個索引熙暴。通過上面的分析就可以發(fā)現(xiàn),force index()指令可以指定本次查詢使用哪個索引慌盯!一條sql只會用到一個索引周霉,mysql優(yōu)化器會計算出一個合適的索引,但是這個索引不一定是最好的亚皂。force index()指令可以避免MySql優(yōu)化器用到了一個低效的索引俱箱。
總結(jié):mysql可能并不總會選擇合適且效率高的索引去查詢,這時適當?shù)膄orce index(indexname) 強制告訴mysql使用什么索引尤為重要孕讳。