一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

Mysql|Sql Server|Oracle|Redis|MongoDB|PostgreSQL|Sqlite|DB2|mariadb|Access|數(shù)據(jù)庫技術(shù)|

服務(wù)器之家 - 數(shù)據(jù)庫 - Mysql - MySQL分頁優(yōu)化

MySQL分頁優(yōu)化

2020-06-05 19:51iVictor Mysql

這篇文章主要為大家詳細(xì)介紹了MySQL分頁優(yōu)化,內(nèi)容思路很詳細(xì),有意對MySQL分頁優(yōu)化的朋友可以參考一下

最近,幫同事重寫了一個(gè)MySQL SQL語句,該SQL語句涉及兩張表,其中一張表是字典表(需返回一個(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ī)定的時(shí)間內(nèi)反饋結(jié)果,于是系統(tǒng)直接報(bào)錯(cuò)。

一般的思路是用MySQL的分頁功能,即直接在原SQL語句后面增加LIMIT子句。但請注意,雖然你看到的反饋結(jié)果只是LIMIT后面指定的數(shù)量,于是想當(dāng)然的以為MySQL只是檢索了指定數(shù)量的數(shù)據(jù),然后給予返回。其實(shí),MySQL內(nèi)部實(shí)現(xiàn)的原理是,檢索所有符合where條件的記錄,然后返回指定數(shù)量的記錄。從這個(gè)角度來看,直接在原SQL語句后面添加LIMIT子句只能說是一種可以實(shí)現(xiàn)功能的方案,但未必最優(yōu)。

具體在本例中,首先我們來看一下150個(gè)字段的表的統(tǒng)計(jì)信息:

MySQL分頁優(yōu)化

一行大概就占2k,而Innodb默認(rèn)頁的大小為16k,這意味著,一個(gè)頁中最多可存儲(chǔ)8行的數(shù)據(jù)。隨機(jī)讀的可能性大大增加。而這無疑會(huì)對數(shù)據(jù)庫系統(tǒng)的IO造成極大的壓力。 

優(yōu)化前

如果采用上述方案,即直接在原SQL語句后面增加LIMIT子句,下面,我們來看看它的執(zhí)行情況。

首先,直接添加LIMIT子句后的SQL語句如下(已省略a1表的150個(gè)字段和a2中的一個(gè)字段):

 

復(fù)制代碼 代碼如下:
FROM upay_csys_scquery_txn_log_his a1  LEFT JOIN upay_csys_trans_code a2 on(a1.int_trans_code=a2.trans_code) WHERE STATUS<>'00' AND settle_date=20151230 limit 50000,10000;


其執(zhí)行時(shí)間如下:

MySQL分頁優(yōu)化

大概執(zhí)行了32s,絕大部分都花費(fèi)到Sending data上了。Sending data指的是服務(wù)器檢索數(shù)據(jù),讀取數(shù)據(jù),并將數(shù)據(jù)返回給客戶端的時(shí)間。

關(guān)于上述執(zhí)行結(jié)果,有以下幾點(diǎn)需要說明:

1. 這是SQL語句多次執(zhí)行后的結(jié)果,這樣就可以排除結(jié)果緩存的影響,事實(shí)上,每次查詢的時(shí)長都是32s左右。

2. 為什么選用的是limit 50000,10000,而不是0,10000,這個(gè)主要是考慮到對于LIMIT子句來說,越到后面,分頁的成本越高。基于此,選擇了中間值來作為分頁的結(jié)果。

該語句的執(zhí)行計(jì)劃如下:

MySQL分頁優(yōu)化

優(yōu)化后:

優(yōu)化的思路:

只對該表的主鍵進(jìn)行分頁,然后用返回的主鍵作為子查詢的結(jié)果,來檢索該表其它字段的值。

改寫后的SQL語句如下:

 

復(fù)制代碼 代碼如下:
FROM upay_csys_scquery_txn_log_his a1  LEFT JOIN upay_csys_trans_code a2 on(a1.int_trans_code=a2.trans_code) where seq_id in (select seq_id from (select seq_id FROM upay_csys_scquery_txn_log_his a1  WHERE STATUS<>'00' AND settle_date=20151230 order by 1 limit 50000,10000) as t);


其執(zhí)行時(shí)間如下:

MySQL分頁優(yōu)化

大概3s多,比第一種方案快了差不多10倍,效果顯著。

下面來看看其執(zhí)行計(jì)劃(explain extended)

MySQL分頁優(yōu)化

 總結(jié):

1. 改寫后的語句原本如下:

 

復(fù)制代碼 代碼如下:
FROM upay_csys_scquery_txn_log_his a1  LEFT JOIN upay_csys_trans_code a2 on(a1.int_trans_code=a2.trans_code) where seq_id in (select seq_id FROM upay_csys_scquery_txn_log_his a1  WHERE STATUS<>'00' AND settle_date=20151230 order by 1 limit 50000,10000);


但MySQL報(bào)以下錯(cuò)誤:

 

復(fù)制代碼 代碼如下:
ERROR 1235 (42000): This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'


需再增加一個(gè)嵌套子查詢,

比如這樣的語句是不能正確執(zhí)行的。

復(fù)制代碼 代碼如下:
select * from table where id in (select id from table limit 12);

但是,只要你再加一層就行。如:

復(fù)制代碼 代碼如下:
select * from table where id in (select t.id from (select * from table limit 12)as t)

這樣就可以繞開limit子查詢的問題。
問題解決。

2. 如果想查看MySQL查詢優(yōu)化器等價(jià)改寫后的SQL語句,可首先通過explain extended得到具體的執(zhí)行計(jì)劃,然后通過show warnings查看。

具體在本例中,等價(jià)改寫后的SQL語句如下:

MySQL分頁優(yōu)化

與設(shè)想中的執(zhí)行順序一致~

3. 如何查看MySQL語句各步驟的執(zhí)行時(shí)間。

以上就是本文的全部內(nèi)容,希望對大家MySQL分頁優(yōu)化有所幫助。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: h片在线看 | 操bb| a在线观看欧美在线观看 | 亚洲欧美成人中文在线网站 | 我和寂寞孕妇的性事 | 亚洲男人的天堂网站 | 处女摘花| 日本破处 | 男男gaygays黑人 | 亚洲第9页 | 8x8x丝袜美女| 魔法满屋免费观看完整版中文 | 欧美视频一区二区专区 | 好男人资源大全免费观看 | 99在线在线视频免费视频观看 | 韩国三级日本三级香港三级黄 | 日韩精品成人免费观看 | 国产成人影院一区二区 | 欧美a级在线观看 | 夫妻性生活免费在线观看 | 欧美精品色精品一区二区三区 | 免费视频一区二区 | 龟甲情感超市全文阅读 小说 | gaychinese男男2022 | 白丝萝莉h | 国产另类视频一区二区三区 | 果冻传媒天美传媒在线小视频播放 | 国产精品久久久久久久久免费观看 | 爸爸的宝贝小说全文在线阅读 | 亚洲欧美午夜 | 日本免费一区二区三区 | 成人啪啪漫画羞羞漫画www网站 | 日本久本草精品 | 日韩特级片 | 国产欧美日韩精品高清二区综合区 | 啪啪无尽3d动漫漫画免费网站 | x8x8在线观看 | 国产亚洲精品线观看77 | caoporm国产精品视频免费 | 欧美性理论片在线观看片免费 | 日本三级欧美三级人妇英文 |