mysql百萬級數據分頁查詢緩慢優化方法


參考網址1:https://www.cnblogs.com/nightOfStreet/p/9647926.html           -------------修改需求

一、與產品商討 修改需求

  • 后端工程師,在接到分頁list需求的時候,內心是這樣的
  1. 畫面是這樣的
  2. 代碼大概是這樣的
    1. select count(id) from …       查出總數
    2. select * from …. limit m,n    查出分頁數據  
  3. 和前端的交互是這樣的
    1. 你傳給我查詢條件和pageNum、pageSize
    2. 我給你返回total、resultList
  4. 恩,可以開始預估開發時間了
    • 結果出來的時候是這樣的
      • 在點擊后面幾頁的時候發現數據加載很慢。不好,一開始沒想到數據量是這個級別的,慢SQL監控已經開始預警
      • 定位到原因有兩個
        • select count(*) 總量會掃全表
        • limit m,n 當偏移量m很大的時候,查詢每次都要先掃到m條滿足條件的記錄
    • 其他人一定也遇到過這個問題,打開百度還沒開始搜索就找到了一個解決方案,百度是這樣做的
      • (正解)我去,這不是耍流氓嗎
        • 沒有總數,就不需要count,第一個問題解決
        • limit m,n 百度出來的解決方案都是加一個唯一標識去記錄上一次查詢的記錄在哪里
      • 百度這種做法是搜索引擎自帶的分頁,不過mysql分頁同樣可以借鑒,找來產品大大溝通一發
        1. “面對這么多的數據,只要把新的數據放到前面,用戶不會care后面的數據,是不是可以把頁碼干掉”
        2. “ 用戶也不會管我們到底有多少條記錄,來這里也只是做檢索而已,總數也可以去掉的,如果要統計數據量我們再單獨統計”
        3. 。。。理由還可以有很多,產品大大還是很好說話的
    • 最后設計出來是這樣的 
      • 代碼實現是這樣的

        • id是自增主鍵 

        • select * from … where id > y order by id limit n (向下翻頁)

        • select * from … where id < y order by id desc limit n (向上翻頁)
      • 和前端的交互是這樣的
        • 你告訴我是向上翻頁還是向下翻頁,給我當前頁第一條(上一頁)或者最后一條(下一頁)記錄的id
        • 我給你數據數據 
    • 總結
      1. 重點是在傳統分頁方案上遇到的兩個問題
        • select count(*) 總量會掃全表
        • limit m,n 當偏移量m很大的時候,查詢每次都要先掃到m條滿足條件的記錄
      2. 解決方案是產品和技術共同確認的結果,如果產品不接受,此方案不可行
      3. 實際開發中還會碰到的問題
        1. 上一頁/下一頁、沒有數據的處理方式
        2. 查詢自身帶有排序條件,需要order by多字段

 

參考網址2:https://www.cnblogs.com/icebutterfly/p/9199202.html

二、優化sql查詢語句

1.子查詢優化法
   先找出第一條數據,然后大於等於這條數據的id就是要獲取的數據
   缺點:數據必須是連續的,可以說不能有where條件,where條件會篩選數據,導致數據失去連續性
   實驗下
    mysql> set profi=1;
   Query OK, 0 rows affected (0.00 sec)
   mysql> select count(*) from Member;
   +———-+
   | count(*) |
   +———-+
   |   169566 |
   +———-+
   1 row in set (0.00 sec)
   mysql> pager grep !~-
   PAGER set to ‘grep !~-‘
   mysql> select * from Member limit 10, 100;
   100 rows in set (0.00 sec)
   mysql> select * from Member where MemberID >= (select MemberID from Member limit 10,1) limit 100;
   100 rows in set (0.00 sec)
   mysql> select * from Member limit 1000, 100;
   100 rows in set (0.01 sec)
   mysql> select * from Member where MemberID >= (select MemberID from Member limit 1000,1) limit 100;
   100 rows in set (0.00 sec)
   mysql> select * from Member limit 100000, 100;
   100 rows in set (0.10 sec)
   mysql> select * from Member where MemberID >= (select MemberID from Member limit 100000,1) limit 100;

 2.倒排表優化法
   倒排表法類似建立索引,用一張表來維護頁數,然后通過高效的連接得到數據
   缺點:只適合數據數固定的情況,數據不能刪除,維護頁表困難
   3.反向查找優化法
   當偏移超過一半記錄數的時候,先用排序,這樣偏移就反轉了
   缺點:order by優化比較麻煩,要增加索引,索引影響數據的修改效率,並且要知道總記錄數
   ,偏移大於數據的一半
   引用
   limit偏移算法:
   正向查找: (當前頁 – 1) * 頁長度
   反向查找: 總記錄 – 當前頁 * 頁長度

 


免責聲明!

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



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