1. 程式人生 > >MYSQL orderBy和limit連用陷阱

MYSQL orderBy和limit連用陷阱

在Mysql中我們常常用order by來進行排序,使用limit來進行分頁,當需要先排序後分頁時我們往往使用類似的寫法select * from 表名 order by 排序欄位 limt M,N。但是這種寫法卻隱藏著較深的使用陷阱。在排序欄位有資料重複的情況下,會很容易出現排序結果與預期不一致的問題。

比如現在有一張user表,表結構及資料如下:

表結構

表資料

現在想根據建立時間升序查詢user表,並且分頁查詢,每頁2條,那很容易寫出sql為:select * from user order by create_time limit pageNo,2;

在執行查詢過程中會發現: 
1、查詢第一頁資料時:

第一頁查詢結果

2、查詢第四頁資料時:

第四頁查詢結果

user表共有8條資料,有4頁資料,但是實際查詢過程中第一頁與第四頁竟然出現了相同的資料。

這是什麼情況?難道上面的分頁SQL不是先將兩個表關聯查詢出來,然後再排好序,再取對應分頁的資料嗎???

上面的實際執行結果已經證明現實與想像往往是有差距的,實際SQL執行時並不是按照上述方式執行的。這裡其實是Mysql會對Limit做優化,具體優化方式見官方文件:https://dev.mysql.com/doc/refman/5.7/en/limit-optimization.html 
這個是5.7版本的說明,提取幾個問題直接相關的點做下說明。

Paste_Image.png

上面官方文件裡面有提到如果你將Limit row_count與order by混用,mysql會找到排序的row_count行後立馬返回,而不是排序整個查詢結果再返回。如果是通過索引排序,會非常快;如果是檔案排序,所有匹配查詢的行(不帶Limit的)都會被選中,被選中的大多數或者全部會被排序,直到limit要求的row_count被找到了。如果limit要求的row_count行一旦被找到,Mysql就不會排序結果集中剩餘的行了。

這裡我們檢視下對應SQL的執行計劃:

Paste_Image.png

可以確認是用的檔案排序,表確實也沒有加額外的索引。所以我們可以確定這個SQL執行時是會找到limit要求的行後立馬返回查詢結果的。

不過就算它立馬返回,為什麼分頁會不準呢?

官方文件裡面做了如下說明: 
Paste_Image.png

如果order by的欄位有多個行都有相同的值,mysql是會隨機的順序返回查詢結果的,具體依賴對應的執行計劃。也就是說如果排序的列是無序的,那麼排序的結果行的順序也是不確定的。

基於這個我們就基本知道為什麼分頁會不準了,因為我們排序的欄位是create_time,正好又有幾個相同的值的行,在實際執行時返回結果對應的行的順序是不確定的。對應上面的情況,第一頁返回的name為8的資料行,可能正好排在前面,而第四頁查詢時name為8的資料行正好排在後面,所以第四頁又出現了。

那這種情況應該怎麼解決呢?

官方給出瞭解決方案: 
Paste_Image.png

如果想在Limit存在或不存在的情況下,都保證排序結果相同,可以額外加一個排序條件。例如id欄位是唯一的,可以考慮在排序欄位中額外加個id排序去確保順序穩定。

所以上面的情況下可以在SQL再添加個排序欄位,比如fund_flow的id欄位,這樣分頁的問題就解決了。修改後的SQL可以像下面這樣: 
SELECT * FROM user ORDER BY create_time,id LIMIT 6,2;

再次測試問題解決!!

相關推薦

MYSQL orderBylimit連用陷阱

在Mysql中我們常常用order by來進行排序,使用limit來進行分頁,當需要先排序後分頁時我們往往使用類似的寫法select * from 表名 order by 排序欄位 limt M,N。但是這種寫法卻隱藏著較深的使用陷阱。在排序欄位有資料重複的情況下,會很容

MyBatis查詢List結果丟失(MysqlOrderBylimit混用導致)

最近做專案遇到持久層使用MyBatis查詢時,出現查詢的結果在log4g日誌中顯示是5條,但是在List中取出的時候只有一條的情況,SQL語句沒有問題.問題原因:   1.首先檢查是否是多表聯查時主鍵重複了2.值得注意的是Mysql中limit和orderBy一起用由於Mys

mysqlorderbylimit同時使用的bug

我的SQL很簡單 我想從一個表中檢索所有標題含有“中國”的資料,將它們按id排序,取前5條,所以我寫了以下語句 SQL語句1: select fi_id, fi_url, fi_title from InfoTable where fi_title like '%中國%' order by fi_id des

mysql 中同時使用orderbygroupby的分析

最近做專案寫sql的時候同時使用到了order by 和 group by.然而查詢出來的結果不是自己想象中的那樣. 下面來分析一樣原因: mysql 寫sql的順序: selec

MySQL等於號不等號的陷阱

在使用delete刪除資料時用<>限制刪除項,結果並沒有得到想要的結果,檢查發現作為<>判斷的欄位如果是null是匹配不到的,仔細測試發現正常情況下等於“=”和不等於(“<>”或“!=”)返回1或0。但是當使用等於和不等於和null比較時結

mysql5.7:mysql安裝基於SSL加密的主從復制(詳細剖析)

mysql ssl db 數據 加密傳輸 小生博客:http://xsboke.blog.51cto.com 小生 Q Q:1770058260 -------謝謝您的參考,如有疑問,歡迎交流目錄:--------my

mysql order by limit 問題

name hsb 出現 .cn cnblogs test mit width 1-1 問題 不使用limit時 使用limit出現問題了: 原因是出現相同值 gaoxiong 解決辦法:使用多個字段排序,上述例子可以改成 select * from hsb_test or

MySQL】配置MySQL安裝遠程訪問步驟

image 新建 oar 最新 rest word clas 字段 sql安裝 以遠程服務器為例,安裝Mysql到Linux並配置遠程訪問,步驟如下: 1.下載安裝最新的rpm文件 方法一: rpm -Uvh http://repo.mysql.com/mysql-co

mysql管理基本操作

sql 修改root密碼 服務 blog sam www 網址 resolve 日誌 進去mysql:mysql –uroot –p 重啟數據庫:[[email protected]/* */ ~]# /etc/init.d/mysqld restart1.

MySQL--約束修改數據表總結

分享 cnblogs 總結 -- logs images http 修改 mysql MySQL--約束和修改數據表總結

mysql啟動關閉外鍵約束的方法

word nbsp 查看 set 外鍵約束 mysql 輸入 check select 關閉外鍵約束,輸入命令:SET FOREIGN_KEY_CHECKS=0; 啟動外鍵約束,輸入命令:SET FOREIGN_KEY_CHECKS=1; 查看當前是否有外鍵約束:SELEC

MySQL事務(一):InnoDB鎖(MySQL 官方文檔粗翻)

空間索引 系統 聚集索引 rds update 能夠 conf 沒有 得到   // 寫在前面,實際上,數據庫加鎖的類型和範圍受到多種因素的影響,例如數據庫隔離等級,SQL語句,是否使用主鍵、索引等等。可以查看博文: http://www.cnblogs.com/zhaoy

laravel 自定義分頁 offset limit 的使用

有一個 信息 代碼 自定義 快速 技術 多少 信息技術 只需要 laravel 本身有一個自帶的快速分頁方法 paginate,只需要傳入每頁顯示多少條數據就可以 了,但是如果想使用自定義從哪裏開始呢,這時候就可以使用offset 和 limit 的組合,offset 設置

mysql優化類型

mysqlMySQL還支持選擇在該類型關鍵字後面的括號內指定整數值的顯示寬度(例如,INT(4))。int(M) 在 integer 數據類型中,M 表示最大顯示寬度,該可選顯示寬度規定用於顯示寬度小於指定的列寬度的值時從左側填滿寬度。 顯示寬度並不限制可以在列內保存的值的範圍,也不限制超過列的指定寬度的值的

mysql字符集排序介紹

mysq 簡體 binary set 服務器 客服 result system nic 客服端字符集: character_set_client utf8mb4連接字符集: character_set_connection utf8mb4數據庫字符集: character_

Linux數據庫:MYSQL啟用查看二進制日誌

server mail etc 文件 查看表 rom 查看 日誌 stat 在/etc/my.cnf文件中【mysqld】下加上: server-id = 1 (在整個Mysql集群中保證唯一) log-bin = binlog log-bin-index = binl

單表60億記錄等大數據場景的MySQL優化運維之道 | 高可用架構

點數據 dump fwe wide 更新 lock redo 可靠 index 015-08-09 楊尚剛 高可用架構 此文是根據楊尚剛在【QCON高可用架構群】中,針對MySQL在單表海量記錄等場景下,業界廣泛關註的MySQL問題的經驗分享整理而成,轉發請註明出處。 楊

mysql 啟動關閉外鍵約束

ext sql 更新 set ... 避免 mysq delete 約束 在MySQL中刪除一張表或一條數據的時候,出現 [Err] 1451 -Cannot delete or update a parent row: a foreign key constrai

【CentOS6.5】MySQL安裝配置

配置 entos alt tro images .com centos ges mys 1./etc/my.cnf 這是mysql的主配置文件 2、數據存放位置 3、錯誤存放位置 【CentOS6.5】MySQL安裝和配置

mysql優化索引

索引 mysql優化 表的優化1.定長與變長分離 如 int,char(4),time核心且常用字段,建成定長,放在一張表; 而varchar,text,blob這種變長字段適合單放一張表,用主鍵與核心表關聯。2.常用字段和不常用字段要分離3.在 1 對多需要關聯統計的字段上,添加冗余字段