常見mysql的慢查詢優化方式


一,第一步.開啟mysql慢查詢  

        方式一:

              修改配置文件  在 my.ini 增加幾行:  主要是慢查詢的定義時間(超過2秒就是慢查詢),以及慢查詢log日志記錄( slow_query_log)

        方法二:通過MySQL數據庫開啟慢查詢:

二,分析慢查詢日志                

       直接分析mysql慢查詢日志 ,利用explain關鍵字可以模擬優化器執行SQL查詢語句,來分析sql慢查詢語句

       例如:執行EXPLAIN SELECT * FROM res_user ORDER BYmodifiedtime LIMIT 0,1000

       得到如下結果: 顯示結果分析:  

       table |  type | possible_keys | key |key_len  | ref | rows | Extra  EXPLAIN列的解釋:           

       table   顯示這一行的數據是關於哪張表的           

       type    這是重要的列,顯示連接使用了何種類型。從最好到最差的連接類型為const、eq_reg、ref、range、indexhe和ALL 

       rows   顯示需要掃描行數

       key     使用的索引

三,常見的慢查詢優化

 (1)索引沒起作用的情況

          1. 使用LIKE關鍵字的查詢語句

               在使用LIKE關鍵字進行查詢的查詢語句中,如果匹配字符串的第一個字符為“%”,索引不會起作用。只有“%”不在第一個位置索引才會起作用。

         2. 使用多列索引的查詢語句

               MySQL可以為多個字段創建索引。一個索引最多可以包括16個字段。對於多列索引,只有查詢條件使用了這些字段中的第一個字段時,索引才會被使用。

 (2)優化數據庫結構

              合理的數據庫結構不僅可以使數據庫占用更小的磁盤空間,而且能夠使查詢速度更快。數據庫結構的設計,需要考慮數據冗余、查詢和更新的速度、字段的數據類型是否合理等多方面的內容。

          1. 將字段很多的表分解成多個表 

                對於字段比較多的表,如果有些字段的使用頻率很低,可以將這些字段分離出來形成新表。因為當一個表的數據量很大時,會由於使用頻率低的字段的存在而變慢。

          2. 增加中間表

                對於需要經常聯合查詢的表,可以建立中間表以提高查詢效率。通過建立中間表,把需要經常聯合查詢的數據插入到中間表中,然后將原來的聯合查詢改為對中間表的查詢,以此來提高查詢效率。

 (3)分解關聯查詢

         將一個大的查詢分解為多個小查詢是很有必要的。

         很多高性能的應用都會對關聯查詢進行分解,就是可以對每一個表進行一次單表查詢,然后將查詢結果在應用程序中進行關聯,很多場景下這樣會更高效,例如:     

 SELECT * FROM tag 
        JOIN tag_post ON tag_id = tag.id
        JOIN post ON tag_post.post_id = post.id
        WHERE tag.tag = 'mysql';
 
        分解為:
 
        SELECT * FROM tag WHERE tag = 'mysql';
        SELECT * FROM tag_post WHERE tag_id = 1234;
        SELECT * FROM post WHERE post.id in (123,456,567); 

   (4)優化LIMIT分頁

         在系統中需要分頁的操作通常會使用limit加上偏移量的方法實現,同時加上合適的order by 子句。如果有對應的索引,通常效率會不錯,否則MySQL需要做大量的文件排序操作。

         一個非常令人頭疼問題就是當偏移量非常大的時候,例如可能是limit 10000,20這樣的查詢,這是mysql需要查詢10020條然后只返回最后20條,前面的10000條記錄都將被舍棄,這樣的代價很高。

         優化此類查詢的一個最簡單的方法是盡可能的使用索引覆蓋掃描,而不是查詢所有的列。然后根據需要做一次關聯操作再返回所需的列。對於偏移量很大的時候這樣做的效率會得到很大提升。

          對於下面的查詢:

          select id,title from collect limit 90000,10;

          該語句存在的最大問題在於limit M,N中偏移量M太大(我們暫不考慮篩選字段上要不要添加索引的影響),導致每次查詢都要先從整個表中找到滿足條件 的前M條記錄,

          之后舍棄這M條記錄並從第M+1條記錄開始再依次找到N條滿足條件的記錄。

          如果表非常大,且篩選字段沒有合適的索引,且M特別大那么這樣的代價是非常高的。 試想,如我們下一次的查詢能從前一次查詢結束后標記的位置開始查找,

          找到滿足條件的100條記錄,並記下下一次查詢應該開始的位置,以便於下一次查詢

          能直接從該位置 開始,這樣就不必每次 查詢都先從整個表中先找到滿足條件的前M條記錄,舍棄,在從M+1開始再找到100條滿足條件的記錄了。

          方法一:慮篩選字段(title)上加索引
                       title字段加索引  (此效率如何未加驗證)

          方法二:先查詢出主鍵id值

                      select id,title from collect where id>=(select id from collect order by id limit 90000,1) limit 10;

                     原理:先查詢出90000條數據對應的主鍵id的值,然后直接通過該id的值直接查詢該id后面的數據。

           方法三:“關延遲聯”
                        如果這個表非常大,那么這個查詢可以改寫成如下的方式:

                       Select news.id, news.description from news inner join (select id from news order by title limit 50000,5) as myNew using(id);

                       這里的“關延遲聯”將大大提升查詢的效率,它讓MySQL掃描盡可能少的頁面,獲取需要的記錄后再根據關聯列回原表查詢需要的所有列。這個技術也可以用在優化關聯查詢中的limit。

           方法四:建立復合索引 acct_id和create_time

                       select * from acct_trans_log WHERE  acct_id = 3095  order by create_time desc limit 0,10

                      注意sql查詢慢的原因都是:引起filesort

 


免責聲明!

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



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