日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

一次SQL查詢優化原理分析(900W+數據從17s到300ms)

瀏覽:346日期:2023-03-06 14:25:18
目錄
  • 前言
  • 證實
  • 參考資料:

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

操作:查詢條件放到子查詢中,子查詢只查主鍵ID,然后使用子查詢中確定的主鍵關聯查詢其他的屬性字段;

原理:1、減少回表操作;
2、可參考《阿里巴巴Java開發手冊(泰山版)》第五章-MySQL數據庫、(二)索引規約、第7條:
【推薦】利用延遲關聯或者子查詢優化超多分頁場景。
說明: MySQL并不是挑過offeset行,而是取offset+N行,然后返回放棄前offset行,返回N行,那當offset特別大的時候,效率就非常的底下,要么控制返回的總頁數,要么對超過特定閾值的頁數進行SQL改寫。
正例: 先快速定位需要獲取的id段,然后再關聯:
SELECT a.* FROM 表1 a,(select id from 表1 where 條件 LIMIT 100000,20) b where a.id = b.id;

-- 優化前SQLSELECT  各種字段FROM `table_name`WHERE 各種條件LIMIT 0,10;
-- 優化后SQLSELECT  各種字段FROM `table_name` main_taleRIGHT JOIN (SELECT  子查詢只查主鍵FROM `table_name`WHERE 各種條件LIMIT 0,10;) temp_table ON temp_table.主鍵 = main_table.主鍵

前言

首先說明一下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

到此這篇關于一次SQL查詢優化原理分析(900W+數據從17s到300ms)的文章就介紹到這了,更多相關SQL查詢優化內容請搜索以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持!

標簽: MsSQL
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
国产精品一区二区三区四区在线观看 | 日韩一区中文| 野花国产精品入口| 成人精品天堂一区二区三区| 国产精品毛片久久| 老牛影视精品| 日韩不卡在线| 久久婷婷av| 91青青国产在线观看精品| 麻豆一区二区在线| 国产aⅴ精品一区二区四区| 成人精品国产亚洲| 欧美成a人国产精品高清乱码在线观看片在线观看久 | 激情久久99| 乱一区二区av| 国产精品免费大片| 国产精品日本一区二区不卡视频 | 午夜欧美理论片| 欧美特黄一级| 蜜臀av国产精品久久久久| 亚洲精品一二| 国产日韩一区二区三区在线| 久久国产欧美日韩精品| 欧美激情网址| 美女一区网站| 亚洲精品1区| 综合干狼人综合首页| 综合激情婷婷| 免费观看亚洲天堂| 国产成人精品亚洲日本在线观看| 精品中文一区| 日韩精品欧美大片| 高清av一区| 伊人影院久久| 国产欧美一区| 神马午夜久久| 亚洲欧美网站在线观看| 国产精品一区二区美女视频免费看 | 九九综合在线| 男女男精品网站| 国产精品久久久久毛片大屁完整版| 精品欧美日韩精品| 国产国产精品| 日韩精品福利一区二区三区| 国产一区丝袜| 欧美日韩国产在线一区| 日韩av电影一区| 日韩在线免费| 亚洲一二三区视频| 国产一区三区在线播放| 蜜臀久久99精品久久一区二区| 麻豆精品91| 欧美国产不卡| 中文在线一区| 国产精品1区在线| 欧美综合另类| 国产精品手机在线播放| 国产精品7m凸凹视频分类| 欧美日本不卡| 欧美成人综合| 国产欧美久久一区二区三区| 亚洲天堂免费电影| 日韩三级视频| 麻豆精品蜜桃| 久久激五月天综合精品| 日韩视频网站在线观看| 日韩精品1区2区3区| 国产精品专区免费| 亚洲人成网站在线在线观看| 国产黄大片在线观看| 四虎精品一区二区免费| 日韩在线短视频| 欧美一区自拍| 在线精品视频在线观看高清| 久久亚洲黄色| 亚洲伊人精品酒店| 久久一级电影| 久久三级毛片| 亚洲性视频在线| 久久中文字幕av| 国产精品乱战久久久| 在线 亚洲欧美在线综合一区| 国产精品自在| 亚洲在线一区| 国产精品二区不卡| 欧美一级二区| 午夜一区在线| 欧美一级鲁丝片| 国产剧情在线观看一区| 丝袜脚交一区二区| 久久九九99| 国产欧美日韩免费观看| 中文一区在线| 久久精品国语| 日韩电影免费网址| 国产伦精品一区二区三区视频 | 亚洲激情五月| 天堂av在线| 久久精品九色| 国产欧美日韩一级| 日韩精品社区| 亚洲综合中文| 丝袜美腿成人在线| 99视频+国产日韩欧美| 成人看片网站| 亚洲精品国产嫩草在线观看| 精品国产乱码久久久久久樱花| 久久精品99国产精品| 亚洲免费资源| 免费日韩精品中文字幕视频在线| 高清av一区二区三区| 成人一区不卡| 成人在线免费观看网站| 免费日韩一区二区三区| 国产麻豆一区二区三区| 亚洲人成亚洲精品| 香蕉视频成人在线观看| 亚洲福利专区| 999久久久国产精品| 日韩中文影院| 91精品蜜臀一区二区三区在线| 亚洲成人va| 99久久亚洲精品蜜臀| 欧美日韩在线播放视频| 亚洲天堂av影院| 国产精品久久久久蜜臀| 鲁鲁在线中文| 欧美中文字幕一区二区| 91久久国产| 91久久中文| 久久国产99| 综合一区二区三区| 综合国产视频| 欧美精品三级在线| 国产黄色精品| 国产91在线播放精品| 日韩欧美二区| 国产精品88久久久久久| 香蕉久久夜色精品国产| 蜜臀av国产精品久久久久| 日本一区福利在线| 国产精品777777在线播放 | 久久激情五月激情| 久久av免费| 亚洲女同av| 国产视频一区三区| 亚洲精品一级| 国产精品嫩草影院在线看| 欧美黄页在线免费观看 | 日韩久久精品| 国产一区视频在线观看免费| 亚洲欧美日韩专区| 日韩av影院| 精品美女久久| 99久久激情| 中文字幕av一区二区三区人| 国产日韩欧美一区| 精品久久精品| 不卡一区2区| 日韩1区2区日韩1区2区| 精品视频网站| 国户精品久久久久久久久久久不卡| 亚洲黄色影院| 国产欧美日韩亚洲一区二区三区| 狠狠久久伊人中文字幕| 狠狠爱www人成狠狠爱综合网| 日韩在线观看一区二区三区| 美女久久久久久| 波多野结衣一区| 国产一区 二区| 日韩欧美精品综合| 中文无码久久精品| 精品三级久久久| 国产精品美女久久久| 国产麻豆一区二区三区精品视频| 日韩中文在线播放| 97成人在线| 久久激情婷婷| 91精品国产自产精品男人的天堂| 国产一区丝袜| 久久亚洲国产精品一区二区| 国产精品**亚洲精品| 伊人久久亚洲热| 美女精品久久| 国产精品美女久久久浪潮软件| 国产精品宾馆| 亚洲一区二区成人| 久久一区视频| 久久成人亚洲| 四季av一区二区凹凸精品| 最新国产拍偷乱拍精品| 开心激情综合| 视频在线观看国产精品| 国产成人调教视频在线观看| 亚洲欧洲一区二区天堂久久| 国产精品三p一区二区| 亚洲男女自偷自拍| 欧美韩日一区| 欧美日韩xxxx| 影音先锋久久|