Mysql大表全表查詢的全過程(分析底層的數(shù)據(jù)流轉(zhuǎn)過程)
Mysql大表全表查詢
當我們需要對一整張大表的數(shù)據(jù)執(zhí)行全量查詢操作,比如select * from t 沒有where條件,整個數(shù)據(jù)有幾千萬條占用內(nèi)存大概 100G,而Mysql所在服務器的內(nèi)存只有8G,那就不直接OOM,將整個數(shù)據(jù)庫打崩了嗎?
剛開始開發(fā)的時候會有這樣的疑問,但是隨著時間的推移知道是不會打崩的,但是為什么不會崩,慢慢地就沒有好奇心了。
下面對整個流程進行分析,主要的沖擊點就是Mysql和InnoDB,所以下面還是分成兩個部分進行分析。
下面的分析同樣適用于所有的查詢流程,只是其他查詢操作流程更復雜,但是數(shù)據(jù)量無論大小都會按照下面的流程執(zhí)行。
查詢整張表其實就是查詢 主鍵聚簇索引的那棵B+樹,比如查詢的就是InnoDB 表 db1. t。
查詢和返回按照java方式理解為 request和response流程,request查詢流程可以理解為:Mysql架構圖 ,即下面分析的是返回的流程:
1、Server層
Server層不會一次調(diào)用InnoDB存儲引擎接口獲取全量數(shù)據(jù),也不是一次將所有數(shù)據(jù)發(fā)生給Mysql客戶端,Mysql是邊讀邊發(fā)送的,發(fā)送的過程中依賴兩個緩存池:
- Mysql的 net buffer,由參數(shù) net_buffer_length控制,默認大小為 16K;即一個查詢不論返回結果多大,讀Mysql的影響就是 net_buffer_length大小。
- 本地網(wǎng)絡棧: Mysql服務器的 socket send buffer【默認配置在/proc/sys/net/core/wmem_default,當寫滿時,會暫停接受net buffer的數(shù)據(jù)】、 Mysql客戶端的 socket receive buffer;
具體的查詢執(zhí)行流程如下:
- 獲取一行,寫到 net buffer 中。這塊內(nèi)存的大小是由參數(shù) net_buffer_length 定義的,默認是 16k。
- 重復獲取行,直到 net buffer 寫滿,調(diào)用網(wǎng)絡接口發(fā)出去。
- 如果發(fā)送成功,就清空 net buffer,然后繼續(xù)取下一行,并寫入 net buffer。
- 如果發(fā)送函數(shù)返回 EAGAIN 或 WSAEWOULDBLOCK,就表示本地網(wǎng)絡棧(socket send buffer)寫滿了,進入等待。直到網(wǎng)絡棧重新可寫,再繼續(xù)發(fā)送。
并且在此數(shù)據(jù)查詢過程當前,底層的表現(xiàn)就是Mysql服務端的socket send buffer 和 Mysql客戶端 socket receive buffer,在不停的發(fā)生和接收數(shù)據(jù)包,因為底層是tcp協(xié)議。
而從表象上看,執(zhí)行 show processlist,查詢到的結果為 Sending to client,所以不能簡單的理解成發(fā)生數(shù)據(jù)給客戶端,僅僅表示服務器端的網(wǎng)絡棧寫滿了。
2、innoDB層
在前面博客分析了InnoDB的架構圖,分為內(nèi)存和磁盤架構。內(nèi)存架構中最大的一塊兒內(nèi)存就是 Buffer Pool,可以占用到物理內(nèi)存的 60~80%。
并且分析了針對當前這種大表查詢流程,會將所有的B+樹緩存頁都在變種的 LRU緩存隊列中過一遍。
所以Mysql將緩存鏈表分成young和old區(qū),使用配置參數(shù) innodb_old_blocks_time控制緩存頁真正加入的young取余的條件。
即大表查詢流程對innodb層的影響就是,將所有主鍵聚簇索引B+樹上的頁,全部在 Buffer Pool內(nèi)部的 LRU鏈的 old區(qū)域全部執(zhí)行一遍,當超過內(nèi)存大小限制時,再從 old鏈的尾部出隊列。流程圖如下:
總結
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
mysql 8.0.22壓縮包完整安裝與配置教程圖解(親測安裝有效)
這篇文章主要介紹了mysql 8.0.22壓縮包完整安裝與配置教程圖解(親測安裝有效),本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-12-12mysql 5.7.20常用下載、安裝和配置方法及簡單操作技巧(解壓版免安裝)
這篇文章主要介紹了mysql 5.7.20常用下載、安裝和配置方法及簡單操作技巧(解壓版免安裝)的相關資料,需要的朋友可以參考下2017-11-11mysql創(chuàng)建函數(shù)出現(xiàn)1418錯誤的解決辦法
本篇文章是對在Mysql中創(chuàng)建函數(shù)報“ERROR 1418”的解決方法進行了詳細的分析介紹,需要的朋友參考下2013-06-06MySQL在生產(chǎn)環(huán)境出現(xiàn)無法啟動的問題解決
在當今的數(shù)據(jù)驅(qū)動世界中,MySQL作為廣泛應用的關系型數(shù)據(jù)庫管理系統(tǒng),在眾多生產(chǎn)環(huán)境中承擔著至關重要的角色,然而,面對復雜多變的業(yè)務場景,MySQL可能會遭遇各類故障和性能瓶頸,本文將深入探討MySQL在生產(chǎn)環(huán)境出現(xiàn)無法啟動的問題解決,需要的朋友可以參考下2024-10-10在MySQL中使用mysqlbinlog flashback的簡單教程
這篇文章主要介紹了在MySQL中使用mysqlbinlog flashback的簡單教程,可以很方便地恢復數(shù)據(jù),作者還列出了使用時一些需要注意的地方,需要的朋友可以參考下2015-05-05MySQL數(shù)據(jù)庫遷移到Oracle數(shù)據(jù)庫的完整步驟記錄
在研發(fā)過程中可能會用到將表數(shù)據(jù)庫中的表結構及數(shù)據(jù)遷移到另外一種數(shù)據(jù)庫中,比如說從mysql中遷移到oracle中,這篇文章主要給大家介紹了關于MySQL數(shù)據(jù)庫遷移到Oracle數(shù)據(jù)庫的完整步驟,需要的朋友可以參考下2024-06-06