MYSQL的大數據量情況下的分頁查詢優化


最近做的項目需要實現一個分頁查詢功能,自己先看了別人寫的方法:

 1     <!-- 查詢 -->
 2     <select id="queryMonitorFolder" parameterType="monitorFolderQuery" resultMap="monitorFolderMap">
 3         select
 4             id, name, type, var_num, erp, createTime, modifyTime
 5         from 
 6             monitor_folder
 7         where
 8             yn = 1
 9         <if test="name != null">
10             and name like concat('%',#{name,jdbcType=VARCHAR},'%')
11         </if>
12         and <![CDATA[id <=]]>
13         (   select 
14                 id 
15             from 
16                 monitor_folder 
17             where 
18                 yn=1 
19                 <if test="name != null">
20                     and name like concat('%',#{name,jdbcType=VARCHAR},'%')
21                 </if>
22             order by id desc limit #{startRowNum},1)
23         order by id desc
24         limit #{pageSize}
25     </select>

當時我個人的思路是:在分頁中使用了兩次查詢,效率比較低。直接使用limit就好了。

查過資料之后,不管是自己的想法還是這個代碼都是有不足的。

limit的標准寫法:

1 SELECT * FROM table  LIMIT [offset,] rows | rows OFFSET offset

比如要查第十個開始的十個,就是limit 10, 10

許多網站的分頁功能的底層實現就是依賴前端給后端傳來一些參數,比如起始頁和頁面大小,來結合limit控制分頁。但是這個地方首先有一個問題:效率。

如果這么寫:

1 SELECT * FROM student LIMIT 10000 , 10;

實際底層執行是從第一行開始找到10010行,再拋棄前面的一萬行。所以當用戶往后翻到很多頁的時候,offset這個值可能就比較大,實際執行效率就會很慢。

一般有幾種做法來彌補。

1,用方法計算出開始和結尾條件,用where語句對查詢進行限制。

1 SELECT * FROM student WHERE ID >= 9990 AND ID <= 9999;

比如前端傳來:pageIndex = 1000, pageSize = 10。 也就是第一千頁,每頁十條。得到這兩個參數之后,直接用方法計算得到需要查詢的數據條件:WHERE id >= 9999 AND id <= 9999。

這樣做的顯著好處就是速度快並且也很好理解。而顯著壞處就是使用限制。什么意思呢,就是說你計算出的這個id的范圍不一定能全部命中。一般數據庫的刪除是修改某個字段表示刪除,這樣的話你計算的id范圍可能就有的記錄被刪除了,同時,前端可能還傳來別的限制條件,比如發帖日期在一個月之內,誰發的帖等等。所以問題的核心就是不能保證計算的范圍都能匹配上。如果這里做的比較粗糙(比如后端這么做,前端也直接拿這些數據顯示),實際的效果就是用戶點開一頁,明明顯示說10條記錄,結果只有5條,而且每一頁的情況還不一致。

2,where語句限制一半,limit控制行數

1 SELECT * FROM student WHERE ID >= 9990 LIMIT 10;

這樣的好處就是不僅效率高了,而且能剛好拿十條。但是這里依然還是有一個問題:不適用於所有情況。具體不適用與什么情況呢?簡單來說就是id和行數不能對應的情況。比如ID本身是無規律離散的,那么計算這個起始ID就不能簡單的pageIndex * pageSize了。

  


免責聲明!

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



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