用對地方的索引可以讓你的大數據量的查詢效率飛起來


前言

之前在做項目的時候,接觸到的千萬級以上的表數據不是太多,對於聯合索引的認知不是太深刻,用索引與不用索引以及索引的創建順序和規則之前的區別不是太明顯,最近手頭有優化查詢千萬級數據量的慢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工程師和從網上查詢的結論是MySQL數據庫通過內部自己判斷最優使用索引,從而來決定使用哪個索引,但是它是否選擇的正確也不一定,所以有時候可以是用force來強制是用合適的索引,但是不提倡使用,如果相應的索引被DBA給刪除了,程序就會報錯了。這時候原本查詢千萬級別數據時,有可能就會從毫秒級別上升為秒級別了,比如前面說的有時候會達到一秒或兩秒左右。

我問DBA,如果field_time有的為空,會不會是索引不生效,DBA說不會,只是如果為空的情況下,這個為空的數據不會被計算在內。

感觸

索引如果用的比較好,那么在操作千萬級別甚至億級別的數據時,也是可以很快的。當查詢的數據量越多時,用聯合索引查詢的速度會越快。以后還得好好深入研究這方面的知識啊,生命有限,知識無涯啊!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM