mysql sql優(yōu)化之 limit 分頁優(yōu)化

在秦張良椎尔店,在漢蘇武節(jié)

LIMIT 分頁性能問題

image.png

上圖出自《高性能MYSQL》

問題sql: 普通limit

EXPLAIN SELECT *  FROM emp ORDER BY id LIMIT 5000000,10 

問題sql執(zhí)行時(shí)間 8.231秒,存在性能問題。

業(yè)務(wù)上的優(yōu)化

1、限制用戶分頁专执,不允許進(jìn)行過大的分頁。比如說百度的分頁郁油,它最多只能跳轉(zhuǎn)到一定頁數(shù)本股,用戶再往下翻頁也只顯示最后一頁攀痊。

2、禁用count(*)痊末,不去查詢總條數(shù)蚕苇,不計(jì)算總頁數(shù),不設(shè)計(jì)跳頁的功能

sql層面優(yōu)化方式

1凿叠、增加冗余的列 “頁碼” 來定位記錄

對條件值可以進(jìn)行估算,對于幾百上千頁的檢索嚼吞,往往不需要很精確盒件。也可以專門增加冗余的列來定位記錄,比如如下的 查詢舱禽,有一個(gè)page列炒刁,指定記錄所在的頁,代價(jià)是在修改數(shù)據(jù)的時(shí)候需要維護(hù)這個(gè)列的數(shù)據(jù)誊稚,如下面的查詢翔始。

 SELECT * FROM emp WHERE page = 100 ORDER BY name;
2、索引覆蓋里伯,延時(shí)關(guān)聯(lián)

使用 索引覆蓋城瞎,延時(shí)關(guān)聯(lián) 的方式,將大大提高查詢效率疾瓮,它讓mysql掃描盡可能少的頁面脖镀,獲取需要訪問的記錄后再根據(jù)關(guān)聯(lián)列回原表查詢需要所有的列。這個(gè)技術(shù)可以用于優(yōu)化關(guān)聯(lián)查詢中的LIMIT字句狼电。

1蜒灰、我們可以使用 SELECT id FROM emp ORDER BY id LIMIT 5000000,10 充當(dāng)子查詢,這樣就只在索引中查詢id肩碟,而不用回表查强窖;然后根據(jù)子查詢得出來的id集合再去查對應(yīng)的select * 數(shù)據(jù)即可;

EXPLAIN SELECT  * FROM emp INNER JOIN (SELECT id FROM emp ORDER BY id LIMIT 5000000,10 )AS tb USING(id)
image.png

最后查詢時(shí)間是 5.4 秒,效果在這里并不理想削祈。但是索引覆蓋翅溺,延時(shí)關(guān)聯(lián) 的優(yōu)化思想是非常好的!它不僅是可以用在這里岩瘦。

3未巫、還有注意一點(diǎn): 能用 INNER JOIN 就不要使用IN。比如在這個(gè)limit優(yōu)化中启昧,我使用的是INNER JOIN 自關(guān)聯(lián)查詢叙凡。如果我使用IN呢?情況會(huì)如何密末?

EXPLAIN SELECT * FROM emp WHERE id IN ( SELECT id from (  SELECT id FROM emp ORDER BY id LIMIT 5000010, 10)tb )  

首先握爷,使用IN 的話最終的查詢時(shí)間是15.7秒跛璧,是使用JOIN的三倍!再來看它的查詢計(jì)劃: 直接多了一個(gè)查詢新啼!

image.png
4追城、計(jì)算出邊界值,直接 BETWEEN AND

可以將limit查詢轉(zhuǎn)換為已知位置的查詢燥撞,讓mysql通過范圍掃描獲得到對應(yīng)的結(jié)果座柱。

EXPLAIN SELECT *  FROM emp WHERE id BETWEEN 5000001 AND 5000010 ORDER BY id 

使用BETWEEN .. AND 最終的時(shí)間是 0.063秒,少去了大量的掃描操作物舒;使用這種方式的前提是必須要知道id的邊界值色洞!同樣id必須是連續(xù)單調(diào)遞增的;如果之間有數(shù)據(jù)被刪除掉冠胯,或者因?yàn)閣here條件過濾掉火诸,那么最終得到的頁數(shù)不會(huì)是10了吧;所以這種方式局限性太大了

5荠察、得到上頁最后一條記錄的id置蜀,然后limit

假設(shè)查詢返回的是 5000001 到 5000011 的記錄,那么下一頁查詢就可以從這個(gè)5000011 開始拿10條數(shù)據(jù)悉盆。這樣做無論翻多少也性能都會(huì)很好盯荤!

EXPLAIN SELECT *  FROM emp WHERE id >= 5000001 ORDER BY id  LIMIT 10

這種方式查詢時(shí)間為 0.067。是limit優(yōu)化的首選舀瓢。不過它不能實(shí)現(xiàn)當(dāng)前頁(無法實(shí)現(xiàn)點(diǎn)擊頁碼跳轉(zhuǎn))廷雅,只能上一頁,下一頁的翻頁京髓。適合app端分頁優(yōu)化航缀;它要求id是遞增的(不能使用uuid等字符串充當(dāng)id),但id可以不連續(xù)(可以使用where過濾堰怨、刪除數(shù)據(jù)芥玉,都不會(huì)影響分頁);我們來看看它的查詢計(jì)劃如下:

image.png

結(jié)合索引優(yōu)化

最終是推薦使用第3個(gè)方法:得到上頁最后一條記錄的id备图,然后limit灿巧;但是若需要同時(shí)進(jìn)行where條件檢索、 order by排序的話就必須參加合適的聯(lián)合索引了揽涮!

比如下面的語句抠藕,使用ename 進(jìn)行l(wèi)ike的模糊查詢, 排序的時(shí)候指定id DESC,ename DESC

EXPLAIN SELECT
    * 
FROM
    emp 
WHERE
    id >= 5000001 
    AND ename LIKE '%a%' 
ORDER BY
    id DESC,
    ename DESC 
    LIMIT 10

那么先看看查詢計(jì)劃:出現(xiàn)了 Using filesort


image.png

然后執(zhí)行下蒋困,執(zhí)行時(shí)間為 4.6秒盾似。需要優(yōu)化!

所以雪标,需要?jiǎng)?chuàng)建聯(lián)合索引如下 index(id,ename)

SHOW INDEX  FROM emp
image.png

最終查詢時(shí)間為:0.089 秒零院,優(yōu)化成功溉跃。再看看它的查詢計(jì)劃:

image.png

很好,已經(jīng)沒有 Using filesort 了

其他方法

1告抄、在網(wǎng)上看到有人這樣做

EXPLAIN SELECT
    * 
FROM
    emp 
WHERE
    id >= ( SELECT id FROM emp ORDER BY id LIMIT 5000001, 1 ) 
    LIMIT 10;

這個(gè)方法和上面講的索引覆蓋 是一樣的撰茎,先從索引中找到id,然后通過id查數(shù)據(jù)打洼。只不過上面是使用JOIN這里使用 >=龄糊。這樣就必須讓id是連續(xù)的了。最終查詢時(shí)間是 4-5 秒募疮。和索引覆蓋差不多

image.png

2绎签、使用Sphinx

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市酝锅,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌奢方,老刑警劉巖搔扁,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蟋字,居然都是意外死亡稿蹲,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進(jìn)店門鹊奖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來苛聘,“玉大人,你說我怎么就攤上這事忠聚∩杌” “怎么了?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵两蟀,是天一觀的道長网梢。 經(jīng)常有香客問我,道長赂毯,這世上最難降的妖魔是什么战虏? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮党涕,結(jié)果婚禮上烦感,老公的妹妹穿的比我還像新娘。我一直安慰自己膛堤,他們只是感情好手趣,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著骑祟,像睡著了一般回懦。 火紅的嫁衣襯著肌膚如雪气笙。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天怯晕,我揣著相機(jī)與錄音潜圃,去河邊找鬼。 笑死舟茶,一個(gè)胖子當(dāng)著我的面吹牛谭期,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播吧凉,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼隧出,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了阀捅?” 一聲冷哼從身側(cè)響起胀瞪,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎饲鄙,沒想到半個(gè)月后凄诞,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡忍级,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年帆谍,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片轴咱。...
    茶點(diǎn)故事閱讀 40,488評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡汛蝙,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出朴肺,到底是詐尸還是另有隱情窖剑,我是刑警寧澤,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布宇挫,位于F島的核電站苛吱,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏器瘪。R本人自食惡果不足惜翠储,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望橡疼。 院中可真熱鬧援所,春花似錦、人聲如沸欣除。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至滔岳,卻和暖如春杠娱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背谱煤。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工摊求, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人刘离。 一個(gè)月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓室叉,卻偏偏與公主長得像,于是被迫代替她去往敵國和親硫惕。 傳聞我的和親對象是個(gè)殘疾皇子茧痕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評論 2 359

推薦閱讀更多精彩內(nèi)容