用對地方的索引可以讓你的大資料量的查詢效率飛起來
前言
之前在做專案的時候,接觸到的千萬級以上的表資料不是太多,對於聯合索引的認知不是太深刻,用索引與不用索引以及索引的建立順序和規則之前的區別不是太明顯,最近手頭有優化查詢千萬級資料量的慢sql的任務,優化前,查詢時間達到了60秒,導致前端請求掛起,做了相應的優化後,查詢千萬級別資料時,速度基本保持在零點幾秒到兩點幾秒之間。
sql
1 SELECT 2 * 3 FROM 4 table 5 WHERE 6 field1 = 'bf1adfe6_f71a_11e6_b131_6c92bf2bf639' 7 AND field_time >= '2018-10-09 00:00:00' 8 AND field_time <= '2018-10-15 23:59:59' 9 AND field3 LIKE CONCAT('模糊查詢欄位', '%') 10 ORDER BY 11 field_time DESC 12 LIMIT 0, 13 5; 14 15 SELECT 16 * 17 FROM 18 table 19 WHERE 20 field1 = 'bf1adfe6_f71a_11e6_b131_6c92bf2bf639' 21 AND field_time >= '2018-10-09 00:00:00' 22 AND field_time <= '2018-10-15 23:59:59' 23 AND field3 LIKE CONCAT('模糊查詢欄位', '%') 24 ORDER BY 25 field_date DESC 26 LIMIT 0, 27 5; 28 29 30 31 SELECT 32 * 33 FROM 34 table 35 WHERE 36 field1 = 'bf1adfe6_f71a_11e6_b131_6c92bf2bf639' 37 ORDER BY 38 field_date DESC 39 LIMIT 0, 40 5;
情景描述
field1、field_time是必填欄位,field3 是非必填欄位。
當查詢的總條數少於5條時,查詢時間會達到60秒左右,資料量有一千多萬條。原因是當查詢總數少於5條時,會掃描全表的資料。
分析
第一個sql,field_time範圍查詢欄位和排序欄位是一個欄位,也有對應的索引,如果field1 、field_time設定為單列索引,則會根據field1通過索引過濾一部分資料,在通過field_time對應的索引進行排序,這會更多的消耗資料庫記憶體,把field1 、field_time設定為聯合索引,則相當於建了field1 索引、(field1 、field_time)索引,共兩個索引,然後再建一個(field1 、field_time、field3)索引, 這樣會大大提高查詢效率,測試結果也是如此,提高6秒左右。
第二個sql,中排序的時間欄位和範圍查詢時間欄位不是同一個欄位,而這兩個欄位都有相應的索引,這樣會導致經過過濾查詢出來的資料再次進行時間上的排序,是比較消耗資料庫記憶體,影響查詢效率的。儘量考慮用同一個時間欄位。
第三個sql,則沒有太多的糾結了,直接用(field1 、field_date)索引就可以了,根據最左字首規則。
問題糾結
sql查詢時,模糊查詢中查詢的資料量不同,那麼用到的索引也不盡相同,公司的DBA工程師和從網上查詢的結論是SQL/">MySQL資料庫通過內部自己判斷最優使用索引,從而來決定使用哪個索引,但是它是否選擇的正確也不一定,所以有時候可以是用force來強制是用合適的索引,但是不提倡使用,如果相應的索引被DBA給刪除了,程式就會報錯了。這時候原本查詢千萬級別資料時,有可能就會從毫秒級別上升為秒級別了,比如前面說的有時候會達到一秒或兩秒左右。
感觸
索引如果用的比較好,那麼在操作千萬級別甚至億級別的資料時,也是可以很快的。當查詢的資料量越多時,用聯合索引查詢的速度會越快。以後還得好好深入研究這方面的知識啊,生命有限,知識無涯啊!