MySQL的limit分頁查詢及性能問題

MySQL 通過 limit 實現(xiàn)分頁查詢熟尉。limit 接收一個或兩個整數(shù)型參數(shù)。如果是兩個參數(shù)膀钠,第一個指定返回記錄行的偏移量,第二個指定返回記錄行的最大數(shù)目训枢。初始記錄行的偏移量是 0托修。為了與 PostgreSQL 兼容,limit 也支持limit a offset b【a:取的記錄數(shù)恒界;b:索引】睦刃。

一、分頁查詢

客戶端通過傳遞 start(頁碼)十酣,pageSize(每頁顯示的條數(shù))兩個參數(shù)去分頁查詢數(shù)據(jù)庫表中的數(shù)據(jù)涩拙。MySql 數(shù)據(jù)庫提供的分頁函數(shù) limit m,n 用法和實際需求不切合,所以就需要根據(jù)實際情況去改寫適合分頁的語句耸采。

1??查詢第1條到第10條的數(shù)據(jù)select * from table limit 0,10;
--->對應需求就是查詢第一頁的數(shù)據(jù):select * from table limit (1-1)*10,10;

2??查詢第11條到第20條的數(shù)據(jù)select * from table limit 10,10;
--->對應需求就是查詢第二頁的數(shù)據(jù):select * from table limit (2-1)*10,10;

3??查詢第21條到第30條的數(shù)據(jù)select * from table limit 20,10;
--->對應需求就是查詢第三頁的數(shù)據(jù):select * from table limit (3-1)*10,10;

由此兴泥,得出符合需求的分頁 sql 格式是:select * from table limit (start-1)*pageSize,pageSize;其中 start 是頁碼,pageSize 是每頁顯示的條數(shù)虾宇。

二搓彻、性能問題

對于小的偏移量,直接用 limit 查詢沒有什么問題嘱朽。隨著數(shù)據(jù)量的增大旭贬,越往后分頁,limit 語句的偏移量越大搪泳,速度也會明顯變慢稀轨。

優(yōu)化思想:
避免數(shù)據(jù)量大時掃描過多的記錄

解決:
子查詢的分頁方式或者 JOIN 分頁方式。JOIN 分頁和子查詢分頁的效率基本在一個等級上岸军,消耗的時間也基本一致奋刽。

一般 MySQL 的主鍵是自增的數(shù)字類型,這種情況下可以使用下面的方式進行優(yōu)化艰赞。以真實的生產(chǎn)環(huán)境的6萬條數(shù)據(jù)的一張表為例佣谐,比較一下優(yōu)化前后的查詢耗時:

-- 傳統(tǒng) limit,文件掃描
select * from table order by id limit 50000,2;
受影響的行: 0
時間:  0.171s

-- 子查詢方式方妖,索引掃描
select * from table
where id >= (select id from table order by id limit 50000 , 1)
limit 2;
受影響的行: 0
時間: 0.035s

-- JOIN 分頁方式
select * from table as t1
join (select id from table order by id limit 50000, 1) as t2
where t1.id <= t2.id order by t1.id limit 2;
受影響的行: 0
時間: 0.036s

可以看到經(jīng)過優(yōu)化性能提高了很多倍台谍。

優(yōu)化原理:
子查詢是在索引上完成的,而普通的查詢是在數(shù)據(jù)文件上完成的。通常來說趁蕊,索引文件要比數(shù)據(jù)文件小得多,所以操作起來也會更有效率仔役。因為要取出所有字段內容掷伙,普通查詢需要跨越大量數(shù)據(jù)塊并取出,而另一種方式直接根據(jù)索引字段定位后又兵,才取出相應內容任柜,效率自然大大提升。因此沛厨,對 limit 的優(yōu)化宙地,是避免直接使用 limit,而是首先獲取到 offset 的 id逆皮,然后直接使用 limit size 來獲取數(shù)據(jù)宅粥。

在實際項目使用,可以利用類似策略模式的方式去處理分頁电谣。例如秽梅,每頁 100 條數(shù)據(jù),判斷如果是 100 頁以內剿牺,就使用最基本的分頁方式企垦;如果大于 100,則使用子查詢的分頁方式晒来。

三钞诡、limit 優(yōu)化。使用合理的分頁方式以提高分頁的效率

  • 使用 limit 實現(xiàn)分頁邏輯湃崩。不僅提高了性能荧降,同時減少了不必要的數(shù)據(jù)庫和應用間的網(wǎng)絡傳輸。
  • 查詢結果只有一條或者只要最大/最小一條記錄竹习,建議用 limit 1誊抛。這是為了使 explain 中 type 列達到 const 類型≌埃“l(fā)imit 1”可以避免全表掃面拗窃,只要找到了對應的一條記錄,就不會繼續(xù)向下掃描了泌辫,效率將會大大提高随夸。當然,如果查詢字段是唯一索引的話震放,沒必要加 limit 1宾毒,因為 limit 的存在主要就是為了防止全表掃描,從而提高性能殿遂,如果一個語句本身可以預知不用全表掃描诈铛,有沒有 limit 乙各,性能的差別并不大。
  • 使用下面 SQL 語句做分頁的時候幢竹,隨著表數(shù)據(jù)量的增加耳峦,直接使用 limit 分頁查詢會越來越慢。
select id,name from product limit 89757, 20

優(yōu)化如下:可以取前一頁的最大行數(shù)的 id焕毫,然后根據(jù)這個最大的 id 來限制下一頁的起點蹲坷。此列中,上一頁最大的 id 是 89756邑飒。SQL 可以采用如下的寫法:

//方案一 :返回上次查詢的最大記錄(偏移量)
select id,name from product where id> 89756 limit 20
//方案二:order by + 索引
select id,name from product order by id  limit 10000循签,10
//方案三:在業(yè)務允許的情況下限制頁數(shù)

理由如下:

  • 當偏移量最大的時候,查詢效率就會越低疙咸,因為 MySQL 并非是跳過偏移量直接去取后面的數(shù)據(jù)县匠,而是先把偏移量+要取的條數(shù),然后再把前面偏移量這一段的數(shù)據(jù)拋棄掉再返回的罕扎。
  • 如果使用優(yōu)化方案一聚唐,返回上次最大查詢記錄(偏移量),這樣可以跳過偏移量腔召,效率提升不少杆查。
  • 方案二使用 order by+索引,也是可以提高查詢效率的臀蛛。
  • 方案三的話亲桦,建議跟業(yè)務討論,有沒有必要查這么多的分頁浊仆。因為絕大多數(shù)用戶都不會往后翻太多頁客峭。
    【強制】 在代碼中寫分頁查詢邏輯時,若 count 為 0 應直接返回抡柿,避免執(zhí)行后面的分頁語句舔琅。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市洲劣,隨后出現(xiàn)的幾起案子备蚓,更是在濱河造成了極大的恐慌,老刑警劉巖囱稽,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件郊尝,死亡現(xiàn)場離奇詭異,居然都是意外死亡战惊,警方通過查閱死者的電腦和手機流昏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人况凉,你說我怎么就攤上這事谚鄙。” “怎么了刁绒?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵襟锐,是天一觀的道長。 經(jīng)常有香客問我膛锭,道長,這世上最難降的妖魔是什么蚊荣? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任初狰,我火速辦了婚禮,結果婚禮上互例,老公的妹妹穿的比我還像新娘奢入。我一直安慰自己,他們只是感情好媳叨,可當我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布腥光。 她就那樣靜靜地躺著,像睡著了一般糊秆。 火紅的嫁衣襯著肌膚如雪武福。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天痘番,我揣著相機與錄音捉片,去河邊找鬼。 笑死汞舱,一個胖子當著我的面吹牛伍纫,可吹牛的內容都是我干的。 我是一名探鬼主播昂芜,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼莹规,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了泌神?” 一聲冷哼從身側響起良漱,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎腻扇,沒想到半個月后债热,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡幼苛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年窒篱,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡墙杯,死狀恐怖配并,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情高镐,我是刑警寧澤溉旋,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站嫉髓,受9級特大地震影響观腊,放射性物質發(fā)生泄漏。R本人自食惡果不足惜算行,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一梧油、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧州邢,春花似錦儡陨、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至呀枢,卻和暖如春胚股,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背硫狞。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工信轿, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人残吩。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓财忽,卻偏偏與公主長得像,于是被迫代替她去往敵國和親泣侮。 傳聞我的和親對象是個殘疾皇子即彪,可洞房花燭夜當晚...
    茶點故事閱讀 42,786評論 2 345