以前在作項目的時候,接觸到的千萬級以上的表數據不是太多,對於聯合索引的認知不是太深入,用索引與不用索引以及索引的建立順序和規則以前的區別不是太明顯,最近手頭有優化查詢千萬級數據量的慢sql的任務,優化前,查詢時間達到了60秒,致使前端請求掛起,作了相應的優化後,查詢千萬級別數據時,速度基本保持在零點幾秒到兩點幾秒之間。前端
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;
field一、field_time是必填字段,field3 是非必填字段。sql
當查詢的總條數少於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)索引就能夠了,根據最左前綴規則。spa
sql查詢時,模糊查詢中查詢的數據量不一樣,那麼用到的索引也不盡相同,公司的DBA工程師和從網上查詢的結論是MySQL數據庫經過內部本身判斷最優使用索引,從而來決定使用哪一個索引,可是它是否選擇的正確也不必定,因此有時候能夠是用force來強制是用合適的索引,可是不提倡使用,若是相應的索引被DBA給刪除了,程序就會報錯了。這時候本來查詢千萬級別數據時,有可能就會從毫秒級別上升爲秒級別了,好比前面說的有時候會達到一秒或兩秒左右。code
我問DBA,若是field_time有的爲空,會不會是索引不生效,DBA說不會,只是若是爲空的狀況下,這個爲空的數據不會被計算在內。blog
索引若是用的比較好,那麼在操做千萬級別甚至億級別的數據時,也是能夠很快的。當查詢的數據量越多時,用聯合索引查詢的速度會越快。之後還得好好深刻研究這方面的知識啊,生命有限,知識無涯啊!排序