為什么MYSQL分頁時使用limit+ order by會出現數據重復問題


問題描述: MYSQL采用limit進行翻頁查詢時,搭配order by ,在翻到第二頁的時候可能會出現第一頁的數據,  示例sql如下:

select  a,b from c where d = 'xxx' order by e desc   limit  5,5

使用上述sql查詢的時候,可能出現和limit 0,5 相同的某條記錄,但是使用select  * 時又不會出現重復的情況

顯然用select * 對於表字段多的時候不可取,所以  解決這個情況 用修改后的sql:

select  a,b from c where d = 'xxx' order by e desc, ID  asc    limit  5,5    // 排序的時候用兩個字段

 

問題原因

MYSQL5.6版本,優化器在遇到order by  limit  語句的時候,做了一個優化,使用了priority queue

使用priority queue目的是在不能使用索引有序性的時候,如果需要排序,並且使用了limit n, 那么只需要在排序的過程中,保留n條記錄即可,這樣雖然不能解決所有記錄都需要排序的開銷,但是只需要sort buffer少量的內存就可以完成排序

priority queue使用了堆排序的排序方法,而堆排序是一個不穩定的排序方法,也就是相同的值可能排序出來的結果和讀出來的數據順序不一致,這就導致了MYSQL5.6出現了第二頁數據重復的問題。

注:MYSQL5.5不存在這個問題

mysql解釋sql語言的執行順序: 

select 

DISTINCT<select_list>

FROM<left_table>

JOIN<right_table>

on <join_condition>

where <where_condition>

group by <group_by_list>

having <having_condition>

order by <order_by_condition>

limit<limit_number>

 

問題解決辦法

辦法1,如開頭的一種方式,排序的時候,把ID顯式的加上

辦法2, 在字段上添加索引,直接按照索引的有序性進行讀取並分頁

 

另:分頁是建立在排序的基礎上,進行數量范圍分割。排序是數據庫提供的功能,分頁是業務衍生出來的應用需求。

 


免責聲明!

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



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