1、引言
公司有個需求,統計短信系統每天status沒成功的電話號碼,然後進行統計分析。爲了省事,我直接用了現成的sql, 該sql是分頁,每次篩選limit一百條,最後合併下,最後不就得出所有的手機號了嗎?
select id from smss where type='0' and status='0' and ctime >= '2020-03-03 00:00:00' and ctime<= '2020-03-03 23:59:59' order by id desc limit 1800,100
由於這個表是個日誌表,相當大,大約有十幾億條數據,翻頁是很慢的,及時有ctime限制而且有索引,大約執行了幾十秒,後續優化了一把。
2、第一次優化
我想優化方案是
1、取出今天的minid
2、 where id > minid order by id asc limt 100
3、取出上一步篩選出來最大的maxid, minid= maxid再次進入2循環取,直到取不到值爲止
問題的關鍵在於minid開始初值我寫的0,爲0的話minid條件不命中,條件第二次纔會有。造成的慢sql
select id, mobile from sms where type='0' and status='0' and ctime >= '2020-03-04 00:00:00' and ctime<= '2020-03-04 23:59:59' order by id asc limit 100
這條sql的原因在於:ctime這個索引根本不起作用,直接用id進行掃描的,所以執行非常慢。
3、第二次優化
1、minid = select min(id) from sms where type='0' and status='0' and ctime >= '2020-03-04 00:00:00' and ctime<= '2020-03-04 23:59:59' 這個執行很快,ctime有索引
2、select id, mobile from sms where id>minid and type='0' and status='0' and ctime >= '2020-03-04 00:00:00' and ctime<= '2020-03-04 23:59:59' order by id asc limit 100
3、從2中結果取出mobiles放在內存中,同時取出這一批次中最大的maxid, minid = maxid
再次循環2取數據,直到取不到爲止,這個就順利解決了
4、總結
對於大翻頁,排序按照區間的最大id爲條件,再去請求數據,這樣能減少掃描的行數,從而減少sql執行時間。