99国产精品欲av蜜臀,可以直接免费观看的AV网站,gogogo高清免费完整版,啊灬啊灬啊灬免费毛片

網易首頁 > 網易號 > 正文 申請入駐

一張900w的數據表,16s執行的SQL優化到300ms?

0
分享至

  一,前言

  證實

  參考資料

  

  有一張財務流水表,未分庫分表,目前的數據量為9555695,分頁查詢使用到了limit,優化之前的查詢耗時16 s 938 ms(execution: 16 s 831 ms, fetching: 107 ms),按照下文的方式調整SQL后,耗時347 ms(execution: 163 ms, fetching: 184 ms);

操作: 查詢條件放到子查詢中,子查詢只查主鍵ID,然后使用子查詢中確定的主鍵關聯查詢其他的屬性字段; 原理: 減少回表操作;
-- 優化前SQL
SELECT 各種字段
FROM `table_name`
WHERE 各種條件
LIMIT 0,10;
-- 優化后SQL
SELECT 各種字段
FROM `table_name` main_tale
RIGHT JOIN
SELECT 子查詢只查主鍵
FROM `table_name`
WHERE 各種條件
LIMIT 0,10;
) temp_table ON temp_table.主鍵 = main_table.主鍵

  找到的原理分析:MySQL 用 limit 為什么會影響性能?

  一,前言

  首先說明一下MySQL的版本:

  mysql> select version();
| version() |
| 5.7.17 |
1 row in set (0.00 sec)

  表結構:

  mysql> desc test;
| Field | Type | Null | Key | Default | Extra |
| id | bigint(20) unsigned | NO | PRI | NULL | auto_increment |
| val | int(10) unsigned | NO | MUL | 0 | |
| source | int(10) unsigned | NO | | 0 | |
3 rows in set (0.00 sec)

  id為自增主鍵,val為非唯一索引。

  灌入大量數據,共500萬:

  mysql> select count(*) from test;
| count(*) |
| 5242882 |
1 row in set (4.25 sec)

  我們知道,當limit offset rows中的offset很大時,會出現效率問題:

  mysql> select * from test where val=4 limit 300000,5;
| id | val | source |
| 3327622 | 4 | 4 |
| 3327632 | 4 | 4 |
| 3327642 | 4 | 4 |
| 3327652 | 4 | 4 |
| 3327662 | 4 | 4 |
5 rows in set (15.98 sec)

  為了達到相同的目的,我們一般會改寫成如下語句:

  mysql> select * from test a inner join (select id from test where val=4 limit 300000,5) b on a.id=b.id;
| id | val | source | id |
| 3327622 | 4 | 4 | 3327622 |
| 3327632 | 4 | 4 | 3327632 |
| 3327642 | 4 | 4 | 3327642 |
| 3327652 | 4 | 4 | 3327652 |
| 3327662 | 4 | 4 | 3327662 |
5 rows in set (0.38 sec)

  時間相差很明顯。

  為什么會出現上面的結果?我們看一下select * from test where val=4 limit 300000,5;的查詢過程:

  查詢到索引葉子節點數據。根據葉子節點上的主鍵值去聚簇索引上查詢需要的全部字段值。

  類似于下面這張圖:

  

  像上面這樣,需要查詢300005次索引節點,查詢300005次聚簇索引的數據,最后再將結果過濾掉前300000條,取出最后5條。MySQL耗費了大量隨機I/O在查詢聚簇索引的數據上,而有300000次隨機I/O查詢到的數據是不會出現在結果集當中的。

  肯定會有人問:既然一開始是利用索引的,為什么不先沿著索引葉子節點查詢到最后需要的5個節點,然后再去聚簇索引中查詢實際數據。這樣只需要5次隨機I/O,類似于下面圖片的過程:

  

  其實我也想問這個問題。

  證實

  下面我們實際操作一下來證實上述的推論:

  為了證實select * from test where val=4 limit 300000,5是掃描300005個索引節點和300005個聚簇索引上的數據節點,我們需要知道MySQL有沒有辦法統計在一個sql中通過索引節點查詢數據節點的次數。我先試了Handler_read_*系列,很遺憾沒有一個變量能滿足條件。

  我只能通過間接的方式來證實:

  InnoDB中有buffer pool。里面存有最近訪問過的數據頁,包括數據頁和索引頁。所以我們需要運行兩個sql,來比較buffer pool中的數據頁的數量。預測結果是運行select * from test a inner join (select id from test where val=4 limit 300000,5);之后,buffer pool中的數據頁的數量遠遠少于select * from test where val=4 limit 300000,5;對應的數量,因為前一個sql只訪問5次數據頁,而后一個sql訪問300005次數據頁。

  select * from test where val=4 limit 300000,5
mysql> select index_name,count(*) from information_schema.INNODB_BUFFER_PAGE where INDEX_NAME in('val','primary') and TABLE_NAME like '%test%' group by index_name;Empty set (0.04 sec)

  可以看出,目前buffer pool中沒有關于test表的數據頁。

  mysql> select * from test where val=4 limit 300000,5;
| id | val | source |
3327622 | 4 | 4 |
| 3327632 | 4 | 4 |
| 3327642 | 4 | 4 |
| 3327652 | 4 | 4 |
| 3327662 | 4 | 4 |
5 rows in set (26.19 sec)

  mysql> select index_name,count(*) from information_schema.INNODB_BUFFER_PAGE where INDEX_NAME in('val','primary') and TABLE_NAME like '%test%' group by index_name;
+------------+----------+
| index_name | count(*) |
+------------+----------+
| PRIMARY | 4098 |
| val | 208 |
+------------+----------+2 rows in set (0.04 sec)

  可以看出,此時buffer pool中關于test表有4098個數據頁,208個索引頁。

  select * from test a inner join (select id from test where val=4 limit 300000,5) ;為了防止上次試驗的影響,我們需要清空buffer pool,重啟mysql。

  mysqladmin shutdown
/usr/local/bin/mysqld_safe &
mysql> select index_name,count(*) from information_schema.INNODB_BUFFER_PAGE where INDEX_NAME in('val','primary') and TABLE_NAME like '%test%' group by index_name;

  Empty set (0.03 sec)

  運行sql:

  mysql> select * from test a inner join (select id from test where val=4 limit 300000,5) b on a.id=b.id;
| id | val | source | id |
| 3327622 | 4 | 4 | 3327622 |
| 3327632 | 4 | 4 | 3327632 |
| 3327642 | 4 | 4 | 3327642 |
| 3327652 | 4 | 4 | 3327652 |
| 3327662 | 4 | 4 | 3327662 |
5 rows in set (0.09 sec)

  mysql> select index_name,count(*) from information_schema.INNODB_BUFFER_PAGE where INDEX_NAME in('val','primary') and TABLE_NAME like '%test%' group by index_name;
+------------+----------+
| index_name | count(*) |
+------------+----------+
| PRIMARY | 5 |
| val | 390 |
+------------+----------+
2 rows in set (0.03 sec)

  我們可以看明顯的看出兩者的差別:第一個sql加載了4098個數據頁到buffer pool,而第二個sql只加載了5個數據頁到buffer pool。符合我們的預測。也證實了為什么第一個sql會慢:讀取大量的無用數據行(300000),最后卻拋棄掉。而且這會造成一個問題:加載了很多熱點不是很高的數據頁到buffer pool,會造成buffer pool的污染,占用buffer pool的空間。 遇到的問題

  為了在每次重啟時確保清空buffer pool,我們需要關閉innodb_buffer_pool_dump_at_shutdown和innodb_buffer_pool_load_at_startup,這兩個選項能夠控制數據庫關閉時dump出buffer pool中的數據和在數據庫開啟時載入在磁盤上備份buffer pool的數據。

  參考資料

  1.https://explainextended.com/2009/10/23/mysql-order-by-limit-performance-late-row-lookups/

  2.https://dev.mysql.com/doc/refman/5.7/en/innodb-information-schema-buffer-pool-tables.html

  END

特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相關推薦
熱點推薦
留學圈的話到底有多炸裂?網友:在日本生活5年,我陪她墮了3次胎

留學圈的話到底有多炸裂?網友:在日本生活5年,我陪她墮了3次胎

解讀熱點事件
2025-07-23 00:10:03
易中天:不殺,留著終是個危險

易中天:不殺,留著終是個危險

尚曦讀史
2025-07-23 01:45:02
特朗普這話一出,菲律賓總統臉色變了....

特朗普這話一出,菲律賓總統臉色變了....

環球時報新聞
2025-07-23 11:38:05
曝山東男籃簽下奧拉迪波,邱彪這是在干啥?難怪楊鳴出言不遜

曝山東男籃簽下奧拉迪波,邱彪這是在干啥?難怪楊鳴出言不遜

姜大叔侃球
2025-07-23 16:14:29
2025年高考分數線猛跌的4所211大學,400多分成功撿漏,實屬罕見

2025年高考分數線猛跌的4所211大學,400多分成功撿漏,實屬罕見

教育導向分享
2025-07-22 19:25:20
我是正師級軍官,參加同學聚會被初戀嘲笑,第二年我轉業任副市長

我是正師級軍官,參加同學聚會被初戀嘲笑,第二年我轉業任副市長

喬生桂
2025-07-22 17:09:49
涼爽倒計時!湖北連發38條預警,即將重回40℃!

涼爽倒計時!湖北連發38條預警,即將重回40℃!

極目新聞
2025-07-23 12:31:27
首次,2名中國大陸出身的華人當選為日本參議院議員

首次,2名中國大陸出身的華人當選為日本參議院議員

徐靜波靜說日本
2025-07-23 07:24:02
梁朝偉和湯唯在《色戒》里“假戲真做”?網友爆出截圖:一目了然

梁朝偉和湯唯在《色戒》里“假戲真做”?網友爆出截圖:一目了然

姜糖先生
2025-06-08 19:31:00
央視曝光!你以為沒壞實際早已“細菌爆表”的5種食物,趕緊扔了

央視曝光!你以為沒壞實際早已“細菌爆表”的5種食物,趕緊扔了

阿傖說事
2025-07-22 08:00:09
二手房拋售狂潮席卷全國:我們制造史詩級變革?將會有什么結果

二手房拋售狂潮席卷全國:我們制造史詩級變革?將會有什么結果

小白鴿財經
2025-07-21 08:36:15
“絕經和出道同時來?”上海街頭驚現她的巨幅海報!網友:笑著笑著就哭了

“絕經和出道同時來?”上海街頭驚現她的巨幅海報!網友:笑著笑著就哭了

環球網資訊
2025-07-23 10:48:19
免費領雞蛋,騙244億養老錢!中國老年人“第一大忽悠”終于倒了

免費領雞蛋,騙244億養老錢!中國老年人“第一大忽悠”終于倒了

新語愛八卦
2025-07-22 17:59:09
5年7500萬!曝比亞迪已暫停贊助國足:因大量球迷抵制國足贊助商

5年7500萬!曝比亞迪已暫停贊助國足:因大量球迷抵制國足贊助商

風過鄉
2025-07-22 20:57:26
實錘?網傳杜建英有丈夫,還有一個36歲大兒子,宗慶后竟然是三哥

實錘?網傳杜建英有丈夫,還有一個36歲大兒子,宗慶后竟然是三哥

壹月情感
2025-07-20 22:06:40
NBA歷史僅10人能在出戰400+場比賽保持70+%勝率 小卡是現役唯一

NBA歷史僅10人能在出戰400+場比賽保持70+%勝率 小卡是現役唯一

直播吧
2025-07-23 19:09:16
宗馥莉叔叔宗澤后接受巴倫中文網獨家采訪,又爆出猛料,令人深思

宗馥莉叔叔宗澤后接受巴倫中文網獨家采訪,又爆出猛料,令人深思

悠閑歷史
2025-07-23 15:55:02
北京化工大學碳纖維錄取通知書能切西瓜,學校招生辦:本科生專屬,明年不再沿用

北京化工大學碳纖維錄取通知書能切西瓜,學校招生辦:本科生專屬,明年不再沿用

極目新聞
2025-07-23 13:36:32
宮魯鳴或卸任,女籃新帥或敲定,62歲,名宿,或成李夢回歸關鍵

宮魯鳴或卸任,女籃新帥或敲定,62歲,名宿,或成李夢回歸關鍵

東球弟
2025-07-23 11:10:02
央視曝光!又一灰色產業鏈暴雷!0成本套現48萬,還不用還?

央視曝光!又一灰色產業鏈暴雷!0成本套現48萬,還不用還?

大魚簡科
2025-07-23 16:17:38
2025-07-23 20:08:49
Meta
Meta
關注java進階架構師送架構
1059文章數 9856關注度
往期回顧 全部

科技要聞

別自嗨了!XREAL徐馳:AI眼鏡只有5歲智商

頭條要聞

印度、孟加拉關切雅魯藏布江下游水電站工程 中方回應

頭條要聞

印度、孟加拉關切雅魯藏布江下游水電站工程 中方回應

體育要聞

英格蘭最紅球星 也是加勒比島國驕傲

娛樂要聞

汪峰森林北同游日本 各帶各娃互不耽誤

財經要聞

律師解析娃哈哈遺產案:遺囑是最大變數

汽車要聞

德系大招放盡 場地極限測試全新奧迪A5L

態度原創

本地
旅游
親子
數碼
公開課

本地新聞

這雙丑鞋“泰”辣眼,跪求內娛不要抄作業

旅游要聞

熱聞|清明假期將至,熱門目的地有哪些?

親子要聞

新年吃什么爸爸說交給孩子們自己決定,又是有趣的一餐

數碼要聞

全漢帶來 VIC GD 系列電源:僅擁有 3 年質保的金牌非模組 ATX

公開課

李玫瑾:為什么性格比能力更重要?

無障礙瀏覽 進入關懷版 主站蜘蛛池模板: 内黄县| 阿城市| 西乌珠穆沁旗| 晋州市| 蕉岭县| 阿图什市| 宜良县| 白玉县| 武平县| 仁怀市| 巴里| 林西县| 马山县| 定结县| 宜兰市| 涟水县| 宝应县| 扎赉特旗| 平阳县| 浙江省| 平邑县| 新郑市| 南阳市| 仙居县| 岑溪市| 沿河| 北辰区| 旬阳县| 岳池县| 湘阴县| 三明市| 广德县| 邢台市| 佛坪县| 色达县| 太和县| 正镶白旗| 隆昌县| 连城县| 和硕县| 团风县|