我是如何把無索引的條件查詢SQL優化了一百倍

今天工作中要對一個千萬級數據量的表進行一個數據統計,但是作爲篩選條件的字段並未加索引,於是測試代碼的時候發現執行起來非常慢,平均在十秒左右,最後想了個辦法進行了優化,大概優化到了零點一秒左右。

具體場景及方案如下:

1、

目的是查詢一個文件信息表中的,某個時間之前的所有視頻類型的文件的容量大小的總和(時間存儲格式爲時間戳),那麼直接寫sql的話,就是

select sum(size) from file_table where file_time < 1557330936 and file_type = 'video'

但是這樣的問題是,where後面兩個字段,都沒有建立索引,數據量大的情況之下,查詢非常慢,而本表的索引除了主鍵,只有另一個完全不相關的字段,而這次操作,也只是偶爾做的,不值得再建立一個索引,那麼我開始思考,咋才能把已有的索引用上呢。

2、

首先確定,如果利用,一定只能利用自增的主鍵(BTREE索引),另一個完全不相關的字段在這個場景沒用。

想辦法把where後面的條件,轉換爲用主鍵字段查詢,那就用到索引了。首先想到的方案爲,(id爲主鍵)

select id from file_table where file_time < 1557330936 order by id desc limit 1

這個sql的目的是查詢出來滿足時間要求的最後一條數據的主鍵id,然後只需查詢id小於這個id的數據就可以了。這條語句雖然也用沒建立索引的字段file_time查詢出來,但是有limit 1限制,查到第一條就可以了,不需要進行全表掃描,所以我大膽推測,會快很多(然後我就被打臉了)。

然後

select sum(size) from file_table where id <= '剛剛查出來的主鍵id' and file_type = 'video'

驗證效率,發現並沒有變快,甚至更慢了,我排查了一下,發現是order by id desc使得前一條語句很慢,果然做事不能靠感覺,我試了下,如果不加倒序,那快的很,問題就出在倒序這一步。看來就算是索引字段,那麼大的表,重新排一遍,也要比較長時間的。

3、

我開始想辦法去掉倒序。其實我一開始都打算去找別的方式實現了,結果靈光一閃,想到,我可以查滿足時間條件的下一條,也就是第一條不滿足時間條件的id,這個和滿足條件的最後一條,不就是挨着的數據嘛!而查不滿足條件的,也就是某某時間之後的第一條數據,就不需要倒序了。sql如下:

select id from file_table where file_time > 1557330936 limit 1
select sum(size) from file_table where id < '剛剛查出來的主鍵id' and file_type = 'video'

在本地mysql測試修改後的效率大概是不使用索引的一百倍,剛剛又趁着大晚上,測試了一下用戶環境的數據,要比本地慢一點,應該是因爲加上了傳輸的時間,以及正式環境比我本地數據要更多些,不過總共加起來,不超過一秒,對於偶爾執行的sql來說,滿足要求了。

4、總結

對於需要條件查詢的大量數據,直接的條件又沒有加索引的情況,可以思考這個條件,是否和其他的加了索引的字段有關聯。本次情景中,兩個條件之中的創建時間條件,剛好和主鍵id一樣,都是順序增加的,於是可以先利用沒有索引的字段,查出來最後一條滿足要求的數據,再用這條數據的帶索引的字段,去查詢所有滿足條件的數據,以此減少避免在無索引情況下掃描全表

這個方式我覺得比較取巧,可能不算是sql語句本身的優化,但是很有效,更多的是一種解決問題的思路,以此記錄,如果能剛好帶給你幫助,那我的記錄就更有價值了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章