色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

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

數據分析與開發 ? 來源:未知 ? 2023-04-14 14:27 ? 次閱讀

有一張財務流水表,未分庫分表,目前的數據量為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各種條件
LIMIT0,10;
--優化后SQL
SELECT各種字段
FROM`table_name`main_tale
RIGHTJOIN
(
SELECT子查詢只查主鍵
FROM`table_name`
WHERE各種條件
LIMIT0,10;
)temp_tableONtemp_table.主鍵=main_table.主鍵

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

前言

首先說明一下MySQL的版本:

mysql>selectversion();
+-----------+
|version()|
+-----------+
|5.7.17|
+-----------+
1rowinset(0.00sec)

表結構:

mysql>desctest;
+--------+---------------------+------+-----+---------+----------------+
|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||
+--------+---------------------+------+-----+---------+----------------+
3rowsinset(0.00sec)

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

灌入大量數據,共500萬:

mysql>selectcount(*)fromtest;
+----------+
|count(*)|
+----------+
|5242882|
+----------+
1rowinset(4.25sec)

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

mysql>select*fromtestwhereval=4limit300000,5;
+---------+-----+--------+
|id|val|source|
+---------+-----+--------+
|3327622|4|4|
|3327632|4|4|
|3327642|4|4|
|3327652|4|4|
|3327662|4|4|
+---------+-----+--------+
5rowsinset(15.98sec)

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

mysql>select*fromtestainnerjoin(selectidfromtestwhereval=4limit300000,5)bona.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|
+---------+-----+--------+---------+
5rowsinset(0.38sec)

時間相差很明顯。

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

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

類似于下面這張圖:45d781ce-d8f7-11ed-bfe3-dac502259ad0.jpg

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

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

45ed9680-d8f7-11ed-bfe3-dac502259ad0.jpg

其實我也想問這個問題。

證實

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

為了證實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*fromtestwhereval=4limit300000,5
mysql>selectindex_name,count(*)frominformation_schema.INNODB_BUFFER_PAGEwhereINDEX_NAMEin('val','primary')andTABLE_NAMElike'%test%'groupbyindex_name;Emptyset(0.04sec)

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

mysql>select*fromtestwhereval=4limit300000,5;
+---------+-----+--------+
|id|val|source|
+---------+-----+--------+|
3327622|4|4|
|3327632|4|4|
|3327642|4|4|
|3327652|4|4|
|3327662|4|4|
+---------+-----+--------+
5rowsinset(26.19sec)

mysql>selectindex_name,count(*)frominformation_schema.INNODB_BUFFER_PAGEwhereINDEX_NAMEin('val','primary')andTABLE_NAMElike'%test%'groupbyindex_name;
+------------+----------+
|index_name|count(*)|
+------------+----------+
|PRIMARY|4098|
|val|208|
+------------+----------+2rowsinset(0.04sec)

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

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

mysqladminshutdown
/usr/local/bin/mysqld_safe&
mysql>selectindex_name,count(*)frominformation_schema.INNODB_BUFFER_PAGEwhereINDEX_NAMEin('val','primary')andTABLE_NAMElike'%test%'groupbyindex_name;

Emptyset(0.03sec)

運行sql:

mysql>select*fromtestainnerjoin(selectidfromtestwhereval=4limit300000,5)bona.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|
+---------+-----+--------+---------+
5rowsinset(0.09sec)

mysql>selectindex_name,count(*)frominformation_schema.INNODB_BUFFER_PAGEwhereINDEX_NAMEin('val','primary')andTABLE_NAMElike'%test%'groupbyindex_name;
+------------+----------+
|index_name|count(*)|
+------------+----------+
|PRIMARY|5|
|val|390|
+------------+----------+
2rowsinset(0.03sec)

我們可以看明顯的看出兩者的差別:第一個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的數據。

審核編輯 :李倩


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 數據
    +關注

    關注

    8

    文章

    7074

    瀏覽量

    89153
  • SQL
    SQL
    +關注

    關注

    1

    文章

    767

    瀏覽量

    44170
  • 數據庫
    +關注

    關注

    7

    文章

    3818

    瀏覽量

    64498

原文標題:一次 SQL 查詢優化原理分析:900W+ 數據,從 17s 到 300ms

文章出處:【微信號:DBDevs,微信公眾號:數據分析與開發】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    文了解MyBatis的查詢原理

    本文通過MyBatis個低版本的bug(3.4.5之前的版本)入手,分析MyBatis的一次完整的查詢流程,配置文件的解析
    的頭像 發表于 10-10 11:42 ?1437次閱讀

    基于索引的SQL語句優化之降龍十八掌

    的范圍信息會放入Oracle的數據字典中。Oracle可以利用這個信息來提取出那些只與SQL查詢相關的數據分區。例如,假設你已經定義了個分
    發表于 09-25 13:24

    個可以將音頻信號延時300ms再輸出的電路,跪求大神回復。

    個可以將音頻信號延時300ms再輸出的電路
    發表于 12-11 17:22

    2017雙11技術揭秘—TDDL/DRDS 的類 KV 查詢優化實踐

    僅在SQL層面進行進優化會非常困難,因此針對這類場景,TDDL/DRDS 配合 AliSQL 提出了全新的解決方案。作者:勵強(君瑜)場景介紹性能優化是企業級應用永恒的話題,關系型
    發表于 12-29 14:29

    CC2530 廣播 300ms以下就會產生發送失敗問題,失敗原因:zBufferFull

    多次測試發現芯片在廣播的時候發送時間短于300ms一次的話就會產生發送失敗的現象,每9失敗幾次,失敗的原因為zBufferFull,而采用單播發送頻率在30ms以下才會產生丟包問題,
    發表于 06-01 00:38

    SQL查詢慢的原因分析總結

    sql 查詢慢的48個原因分析 1、沒有索引或者沒有用到索引(這是查詢慢最常見的問題,是程序設計的缺陷)。 2、I/O吞吐量小,形成了瓶頸效應。 3、沒有創建計算列導致
    發表于 03-08 11:58 ?0次下載

    基于關系代數樹的查詢優化方法實例分析

    提出了基于關系代數樹結構的SQL查詢優化策略。利用改進查詢計劃的代數定律,分析基于關系代數樹的關系代數式
    發表于 05-07 10:11 ?21次下載
    基于關系代數樹的<b class='flag-5'>查詢</b><b class='flag-5'>優化</b>方法實例<b class='flag-5'>分析</b>

    基于KingView的SQL數據查詢設計_楊洋

    基于KingView的SQL數據查詢設計_楊洋
    發表于 01-17 19:57 ?0次下載

    企業海量數據查詢優化

    查詢分析、統計操作所基于的SELECT語句在SQL語句中又是付出資源代價最大的語句。舉個具體的例子,比如數據庫表有上百萬甚至上千萬條記
    發表于 12-14 16:40 ?8次下載

    SQL優化器原理 - 查詢優化器綜述

    摘要:?本文主要是對數據查詢優化器的個綜述,包括查詢優化器分類、
    發表于 07-24 17:38 ?326次閱讀
    <b class='flag-5'>SQL</b><b class='flag-5'>優化</b>器原理 - <b class='flag-5'>查詢</b><b class='flag-5'>優化</b>器綜述

    SQL查詢優化是怎么回事

    查詢 (Subquery)的優化直以來都是 SQL 查詢優化中的難點之
    的頭像 發表于 02-01 13:55 ?2066次閱讀
    <b class='flag-5'>SQL</b>子<b class='flag-5'>查詢</b><b class='flag-5'>優化</b>是怎么回事

    SQL優化思路與經典案例分析

    如何定位慢SQL呢、我們可以通過慢查詢日志來查看慢SQL。默認的情況下呢,MySQL數據庫是不開啟慢查詢日志(slow query log)
    的頭像 發表于 10-27 13:16 ?927次閱讀

    文終結SQL查詢優化

    查詢(Subquery)的優化直以來都是 SQL 查詢優化中的難點之
    的頭像 發表于 04-28 14:19 ?772次閱讀
    <b class='flag-5'>一</b>文終結<b class='flag-5'>SQL</b>子<b class='flag-5'>查詢</b><b class='flag-5'>優化</b>

    Oracle長耗時SQL優化案例

    最近在生產客服平臺,運營崗老師反饋,個2w人的企業,在信息詳情查詢時,加載時間過長,越70s左右出結果,需要后臺優化
    的頭像 發表于 05-19 15:02 ?1045次閱讀

    oracle執行sql查詢語句的步驟是什么

    Oracle數據庫是種常用的關系型數據庫管理系統,具有強大的SQL查詢功能。Oracle執行SQL
    的頭像 發表于 12-06 10:49 ?987次閱讀
    主站蜘蛛池模板: 免费视频亚洲| 国产超嫩一线天在线播放 | 久久精品国产免费中文| 成片免费观看视频在线网| 又粗又大又爽又黄的免费视频| 日本亚洲欧洲免费旡码| 久久精品国产eeuss| 国产精品亚洲AV毛片一区二区三区| 97亚洲狠狠色综合久久位 | 动漫美女被到爽了流| 中文字幕欧美日韩VA免费视频| 无罩看奶禁18| 日本午夜精品理论片A级APP发布| 久久精品国产欧美| 国产亚洲精品网站在线视频| 成人 迅雷下载| 97午夜伦伦电影理论片| 孕交videosgratis乌克兰| 亚洲AV无码一区二区色情蜜芽 | 亚洲综合久久一本伊伊区| 双腿被绑成M型调教PLAY照片| 暖暖日本 在线 高清| 久久视频这有精品63在线国产| 国产制服丝袜91在线| 国产高清在线观看| 成人综合在线观看| 2021国产精品视频| 一边捏奶头一边啪高潮会怎么样 | 袖珍人与大黑人性视频| 日日干日日操日日射| 日本后进式猛烈xx00动态图| 免费视频网站嗯啊轻点| 美女露出逼| 久啪久久全部视频在线| 精品久久久久中文字幕日本 | 久久大香线蕉综合爱| 精品粉嫩BBWBBZBBW| 国产一区二区三区影院| 国产精品综合AV一区二区国产馆| 干丝袜美女| 国产AV视频二区在线观看|