MySQL分頁(yè)優(yōu)化
最近,幫同事重寫了一個(gè)MySQL SQL語(yǔ)句,該SQL語(yǔ)句涉及兩張表,其中一張表是字典表(需返回一個(gè)字段),另一張表是業(yè)務(wù)表(本身就有150個(gè)字段,需全部返回),當(dāng)然,字段的個(gè)數(shù)是否合理在這里不予評(píng)價(jià)。平時(shí),返回的數(shù)據(jù)大概5w左右,系統(tǒng)尚能收到數(shù)據(jù)。但12月31日那天,數(shù)據(jù)量大概20w,導(dǎo)致SQL執(zhí)行時(shí)間過(guò)長(zhǎng),未能在規(guī)定的時(shí)間內(nèi)反饋結(jié)果,于是系統(tǒng)直接報(bào)錯(cuò)。
一般的思路是用MySQL的分頁(yè)功能,即直接在原SQL語(yǔ)句后面增加LIMIT子句。但請(qǐng)注意,雖然你看到的反饋結(jié)果只是LIMIT后面指定的數(shù)量,于是想當(dāng)然的以為MySQL只是檢索了指定數(shù)量的數(shù)據(jù),然后給予返回。其實(shí),MySQL內(nèi)部實(shí)現(xiàn)的原理是,檢索所有符合where條件的記錄,然后返回指定數(shù)量的記錄。從這個(gè)角度來(lái)看,直接在原SQL語(yǔ)句后面添加LIMIT子句只能說(shuō)是一種可以實(shí)現(xiàn)功能的方案,但未必最優(yōu)。
具體在本例中,首先我們來(lái)看一下150個(gè)字段的表的統(tǒng)計(jì)信息:
一行大概就占2k,而Innodb默認(rèn)頁(yè)的大小為16k,這意味著,一個(gè)頁(yè)中最多可存儲(chǔ)8行的數(shù)據(jù)。隨機(jī)讀的可能性大大增加。而這無(wú)疑會(huì)對(duì)數(shù)據(jù)庫(kù)系統(tǒng)的IO造成極大的壓力。
優(yōu)化前
如果采用上述方案,即直接在原SQL語(yǔ)句后面增加LIMIT子句,下面,我們來(lái)看看它的執(zhí)行情況。
首先,直接添加LIMIT子句后的SQL語(yǔ)句如下(已省略a1表的150個(gè)字段和a2中的一個(gè)字段):
其執(zhí)行時(shí)間如下:
大概執(zhí)行了32s,絕大部分都花費(fèi)到Sending data上了。Sending data指的是服務(wù)器檢索數(shù)據(jù),讀取數(shù)據(jù),并將數(shù)據(jù)返回給客戶端的時(shí)間。
關(guān)于上述執(zhí)行結(jié)果,有以下幾點(diǎn)需要說(shuō)明:
1. 這是SQL語(yǔ)句多次執(zhí)行后的結(jié)果,這樣就可以排除結(jié)果緩存的影響,事實(shí)上,每次查詢的時(shí)長(zhǎng)都是32s左右。
2. 為什么選用的是limit 50000,10000,而不是0,10000,這個(gè)主要是考慮到對(duì)于LIMIT子句來(lái)說(shuō),越到后面,分頁(yè)的成本越高?;诖?,選擇了中間值來(lái)作為分頁(yè)的結(jié)果。
該語(yǔ)句的執(zhí)行計(jì)劃如下:
優(yōu)化后:
優(yōu)化的思路:
只對(duì)該表的主鍵進(jìn)行分頁(yè),然后用返回的主鍵作為子查詢的結(jié)果,來(lái)檢索該表其它字段的值。
改寫后的SQL語(yǔ)句如下:
其執(zhí)行時(shí)間如下:
大概3s多,比第一種方案快了差不多10倍,效果顯著。
下面來(lái)看看其執(zhí)行計(jì)劃(explain extended)
總結(jié):
1. 改寫后的語(yǔ)句原本如下:
但MySQL報(bào)以下錯(cuò)誤:
需再增加一個(gè)嵌套子查詢,
比如這樣的語(yǔ)句是不能正確執(zhí)行的。
但是,只要你再加一層就行。如:
這樣就可以繞開(kāi)limit子查詢的問(wèn)題。
問(wèn)題解決。
2. 如果想查看MySQL查詢優(yōu)化器等價(jià)改寫后的SQL語(yǔ)句,可首先通過(guò)explain extended得到具體的執(zhí)行計(jì)劃,然后通過(guò)show warnings查看。
具體在本例中,等價(jià)改寫后的SQL語(yǔ)句如下:
與設(shè)想中的執(zhí)行順序一致~
3. 如何查看MySQL語(yǔ)句各步驟的執(zhí)行時(shí)間。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家MySQL分頁(yè)優(yōu)化有所幫助。
- MySql分頁(yè)時(shí)使用limit+order by會(huì)出現(xiàn)數(shù)據(jù)重復(fù)問(wèn)題解決
- 為什么MySQL分頁(yè)用limit會(huì)越來(lái)越慢
- mysql分頁(yè)的limit參數(shù)簡(jiǎn)單示例
- 淺談MySQL分頁(yè)Limit的性能問(wèn)題
- MySQL分頁(yè)Limit的優(yōu)化過(guò)程實(shí)戰(zhàn)
- mysql分頁(yè)性能探索
- 淺析Oracle和Mysql分頁(yè)的區(qū)別
- SpringMVC+Mybatis實(shí)現(xiàn)的Mysql分頁(yè)數(shù)據(jù)查詢的示例
- 利用Spring MVC+Mybatis實(shí)現(xiàn)Mysql分頁(yè)數(shù)據(jù)查詢的過(guò)程詳解
- mysql分頁(yè)時(shí)offset過(guò)大的Sql優(yōu)化經(jīng)驗(yàn)分享
- MySQL分頁(yè)分析原理及提高效率
- MySQL優(yōu)化案例系列-mysql分頁(yè)優(yōu)化
- 你應(yīng)該知道的PHP+MySQL分頁(yè)那點(diǎn)事
- MYSQL分頁(yè)limit速度太慢的優(yōu)化方法
- MySQL分頁(yè)技術(shù)、6種分頁(yè)方法總結(jié)
- 8種MySQL分頁(yè)方法總結(jié)
- mysql分頁(yè)原理和高效率的mysql分頁(yè)查詢語(yǔ)句
- MySQL的幾種分頁(yè)方式,你知道幾種方式
相關(guān)文章
mysql復(fù)制data文件遷移的實(shí)現(xiàn)步驟
有時(shí)候,我們需要遷移整個(gè)數(shù)據(jù)庫(kù),包括數(shù)據(jù)文件,本文將介紹如何通過(guò)復(fù)制MySQL的data文件來(lái)完成數(shù)據(jù)庫(kù)遷移,具有一定的參考價(jià)值,感興趣的可以了解一下2023-11-11MySQL 主從同步,事務(wù)回滾的實(shí)現(xiàn)原理
這篇文章主要介紹了MySQL 主從同步,事務(wù)回滾的實(shí)現(xiàn)原理,幫助大家更好的理解和使用MySQL,感興趣的朋友可以了解下2020-12-12mysql 強(qiáng)大的trim() 函數(shù)
這篇文章主要介紹了mysql 強(qiáng)大的trim() 函數(shù)使用方法,需要的朋友可以參考下2014-03-03小型Drupal數(shù)據(jù)庫(kù)備份以及大型站點(diǎn)MySQL備份策略分享
為了防止web服務(wù)器出現(xiàn)故障而引起的數(shù)據(jù)丟失,數(shù)據(jù)庫(kù)備份顯得非常重要,以免出現(xiàn)重大損失。本文分析研究一下小型的Drupal站的備份策略以及大型站點(diǎn)的mysql備份策略2014-11-11MYSQL設(shè)置觸發(fā)器權(quán)限問(wèn)題的解決方法
這篇文章主要介紹了MYSQL設(shè)置觸發(fā)器權(quán)限問(wèn)題的解決方法,需要的朋友可以參考下2014-09-09MySQL 實(shí)現(xiàn)lastInfdexOf的功能案例
這篇文章主要介紹了MySQL 實(shí)現(xiàn)lastInfdexOf的功能案例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12