MySQL 單表可以放多少數(shù)據(jù),最多 2000 萬?
當(dāng)前位置:點(diǎn)晴教程→知識(shí)管理交流
→『 技術(shù)文檔交流 』
關(guān)于單表能存多少數(shù)據(jù),阿里 JAVA 開發(fā)手冊(cè)提出,建議最大 2000 萬。 然后也看過一篇文章,可以往單表塞 1 億。 當(dāng)然,以上其實(shí)都有一些理論支撐,但是都不全面,也沒有結(jié)合具體實(shí)際的場(chǎng)景。 這篇文章,結(jié)合之前學(xué)習(xí)的知識(shí),進(jìn)行一個(gè)整體匯總,并貼合實(shí)際場(chǎng)景展開。 不 BB,上文章目錄。 01 理論知識(shí)B+ 樹MySQL 的底層結(jié)構(gòu)用 B+ 樹存儲(chǔ),這個(gè)估計(jì)地球人都知道。 為了便于后續(xù)講解,先普及幾個(gè)概念:
下圖是聚集索引,3 層 B+ 樹的結(jié)構(gòu): 虛線部分,可以找到對(duì)應(yīng)頁碼的數(shù)據(jù),這里很基礎(chǔ),不去過多解讀。 頁存儲(chǔ)B+ 樹節(jié)點(diǎn)的存儲(chǔ)結(jié)構(gòu)是 “頁”,一頁的大小 16 KB。 下面是頁結(jié)構(gòu)示意圖: 再看看對(duì)頁結(jié)構(gòu)的解讀: 那一頁能留多少存儲(chǔ)空間呢? 除了 User Records 和 Free Space 以外所占用的存儲(chǔ)是 38 + 56 + 26 + 8 = 128。 當(dāng)新記錄插入到 InnoDB 聚集索引中時(shí),InnoDB 會(huì)嘗試留出 1/16 的頁面空閑以供將來插入和更新索引記錄,所以就只剩下 15/16。 可存儲(chǔ)空間 = 15/16 * 1024 - 128 = 15232 字節(jié)。 這或許是一個(gè)對(duì)你有用的開源項(xiàng)目,mall項(xiàng)目是一套基于 SpringBoot3 + Vue 的電商系統(tǒng)(Github標(biāo)星60K),后端支持多模塊和 2024最新微服務(wù)架構(gòu) ,采用Docker和K8S部署。包括前臺(tái)商城項(xiàng)目和后臺(tái)管理系統(tǒng),能支持完整的訂單流程!涵蓋商品、訂單、購(gòu)物車、權(quán)限、優(yōu)惠券、會(huì)員、支付等功能! 項(xiàng)目演示: 行存儲(chǔ)MySQL 的數(shù)據(jù)是行存儲(chǔ),MySQL 5.6 默認(rèn)行格式為 COMPACT(緊湊),5.7 及以后的默認(rèn)行為 DYNAMIC(動(dòng)態(tài))。 下面是行結(jié)構(gòu)示意圖: 再看看對(duì)行結(jié)構(gòu)的解讀: 02 葉子節(jié)點(diǎn)計(jì)算3 層 B+ 樹最大數(shù)據(jù)量前面說了,我們的 B+ 樹是 3 層,第一層就一個(gè)根節(jié)點(diǎn),能存放 X 個(gè)指針。 第二層的每個(gè)節(jié)點(diǎn),也能存放 X 個(gè)指針,指向第三層 X 個(gè)節(jié)點(diǎn)。 第三層的每個(gè)節(jié)點(diǎn),存放 Y 個(gè)數(shù)據(jù)。 3 層 B+ 樹最大數(shù)據(jù)量 = x ^ 2 * y。 葉子節(jié)點(diǎn)總數(shù) x ^ 2 計(jì)算我們先看一頁能存儲(chǔ)多少個(gè)指針?biāo)饕?/span> 每一條索引記錄當(dāng)中都包含了當(dāng)前索引的值 、一個(gè) 6 字節(jié)的指針信息 、一個(gè) 5 字節(jié)的行標(biāo)頭,用來指向下一層數(shù)據(jù)頁的指針。
假設(shè)我們的主鍵 id 為 bigint 型,也就是 8 字節(jié)。 索引指針大小:8 + 6 + 5 = 19 字節(jié)。 前面已經(jīng)算出,每頁可存儲(chǔ)空間 15232 字節(jié)。 單頁可存儲(chǔ)索引指針:15232 / 19 ≈ 801 條。 那算上頁目錄的話,按每個(gè)槽平均 6 條數(shù)據(jù)計(jì)算的話,至少有 801 / 6 ≈ 134 個(gè)槽,需要占用 268 字節(jié)的空間。 把存數(shù)據(jù)的空間分一點(diǎn)給槽的話,我算出來大約可以存 787 條索引數(shù)據(jù)。 單頁數(shù)據(jù)存儲(chǔ)索引指針:
葉子節(jié)點(diǎn)總數(shù):
03 總記錄數(shù)計(jì)算溢出頁前面提到過,MySQL 行存儲(chǔ)格式包括 COMPACT 和 DYNAMIC,我們這里只看 DYNAMIC。 DYNAMIC 怎么理解? 在一行數(shù)據(jù)中,當(dāng)某列太長(zhǎng)時(shí),葉子節(jié)點(diǎn)無需將該數(shù)據(jù)直接存儲(chǔ) ,而是存儲(chǔ)指向該數(shù)據(jù)的指針,真實(shí)數(shù)據(jù)全部存儲(chǔ)在溢出頁。 使用 DYNAMIC 格式,較短的列會(huì)盡可能保留在 B+ 樹節(jié)點(diǎn)中,從而最大限度地減少給定行所需的溢出頁數(shù)。 那 COMPACT 呢? COMPACT 行格式則是將前 768 個(gè)字節(jié)和 20 字節(jié)的指針存儲(chǔ)在 B+ 樹節(jié)點(diǎn)的記錄中,其余部分存儲(chǔ)在溢出頁上。 這里我們只討論 DYNAMIC 情況。 最少總記錄數(shù)前面我們提到,最大行長(zhǎng)度略小于數(shù)據(jù)庫(kù)頁面的一半,之所以是略小于一半,是由于每個(gè)頁面還留了點(diǎn)空間給頁格式的其他內(nèi)容,所以我們可以認(rèn)為每個(gè)頁面最少能放兩條數(shù)據(jù),每條數(shù)據(jù)略小于 8 KB。 如果某行的數(shù)據(jù)長(zhǎng)度超過這個(gè)值,那 InnoDB 肯定會(huì)分一些數(shù)據(jù)到 溢出頁當(dāng)中去了,所以我們不考慮。 那每條數(shù)據(jù) 8 KB 的話,每個(gè)葉子節(jié)點(diǎn)就只能存放 2 條數(shù)據(jù)。 在主鍵為 int 的情況下, 最多總記錄數(shù)假設(shè)我們的表是這樣的:
先來分析一下這張表的行數(shù)據(jù):無 null 值列表,無可變長(zhǎng)字段列表,需要算上事務(wù) ID 和指針字段,需要算上行記錄頭。 每行數(shù)據(jù)占用空間:4 + 4 + 4 + 6 + 7 + 5 = 30。 每個(gè)葉子節(jié)點(diǎn)存放:15232 ÷ 30 ≈ 507。 算上頁目錄槽位所占空間,每個(gè)葉子節(jié)點(diǎn)可存放 502 條。 在主鍵為 int 的情況下, 04 實(shí)際場(chǎng)景上面的場(chǎng)景是兩個(gè)極端, 我們看一個(gè)具體的示例。
分析一下這張表的行記錄:
再看看字段內(nèi)容信息:
統(tǒng)計(jì)上面的所有分析,共占用 869 字節(jié),則每個(gè)葉子節(jié)點(diǎn)可以存放 15232 ÷ 869 ≈ 17 條,算上頁目錄,仍然能放 17 條。 主鍵為 bigint, 閱讀原文:原文鏈接 該文章在 2025/7/7 11:39:52 編輯過 |
關(guān)鍵字查詢
相關(guān)文章
正在查詢... |