国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

你的mysql到底能存多少數(shù)據(jù)呢?

這篇具有很好參考價(jià)值的文章主要介紹了你的mysql到底能存多少數(shù)據(jù)呢?。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

前言

參考借鑒文章 我說(shuō)MySQL每張表最好不超過(guò)2000萬(wàn)數(shù)據(jù),面試官讓我回去等通知?
這里自己在總結(jié)一下,原因是相關(guān)知識(shí)欠缺,看別人的文章研究很久才弄明白,所以這里記錄一些心得。

作者:阿桿
鏈接:https://juejin.cn/post/7165689453124517896
來(lái)源:稀土掘金
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。

拋磚

很多人說(shuō),MySQL每張表最好不要超過(guò)2000萬(wàn)條數(shù)據(jù),否則就會(huì)導(dǎo)致性能下降。阿里的Java開(kāi)發(fā)手冊(cè)上也提出:?jiǎn)伪硇袛?shù)超過(guò) 500 萬(wàn)行或者單表容量超過(guò) 2GB,才推薦進(jìn)行分庫(kù)分表。
但實(shí)際上,這個(gè)2000萬(wàn)或者500萬(wàn)都只是一個(gè)大概的數(shù)字,并不適用于所有場(chǎng)景,如果盲目的以為表數(shù)據(jù)只要不超過(guò)2000萬(wàn)條就沒(méi)問(wèn)題了,很可能會(huì)導(dǎo)致系統(tǒng)的性能大幅下降。
實(shí)際情況下,每張表由于自身的字段不同、字段所占用的空間不同等原因,它們?cè)谧罴研阅芟驴梢源娣诺臄?shù)據(jù)量也就不同。

引玉

概念

簡(jiǎn)單講一下:
你的mysql到底能存多少數(shù)據(jù)呢?

  1. 一張數(shù)據(jù)表一般對(duì)應(yīng)一顆或多顆樹(shù)的存儲(chǔ),樹(shù)的數(shù)量與建索引的數(shù)量有關(guān),每個(gè)索引都會(huì)有一顆單獨(dú)的樹(shù)。

  2. 聚簇索引和非聚簇索引:
    主鍵索引也是聚簇索引(非葉子節(jié)點(diǎn)):只存儲(chǔ)主鍵和索引列等索引數(shù)據(jù)。
    非主鍵索引都是非聚簇索引(葉子節(jié)點(diǎn)):存儲(chǔ)真正的所有字段信息。

  3. B+樹(shù)的查詢是從上往下一層層查詢的,一般情況下我們認(rèn)為B+樹(shù)的高度保持在3層以內(nèi)是比較好的,也就是上兩層是索引,最后一層存數(shù)據(jù),這樣查表的時(shí)候只需要進(jìn)行3次磁盤(pán)IO就可以了(實(shí)際上會(huì)少一次,因?yàn)楦?jié)點(diǎn)會(huì)常駐內(nèi)存),且能夠存放的數(shù)據(jù)量也比較可觀。

    如果數(shù)據(jù)量過(guò)大,導(dǎo)致B+數(shù)變成4層了,則每次查詢就需要進(jìn)行4次磁盤(pán)IO了,從而使性能下降。所以我們才會(huì)去計(jì)算InnoDB的3層B+樹(shù)最多可以存多少條數(shù)據(jù)。

  4. MySQL每個(gè)節(jié)點(diǎn)大小默認(rèn)為16KB,也就是每個(gè)節(jié)點(diǎn)最多存16KB的數(shù)據(jù),可以修改,最大64KB,最小4KB。

節(jié)點(diǎn)存儲(chǔ)

在Innodb的B+樹(shù)中,我們常說(shuō)的節(jié)點(diǎn)被稱之為 頁(yè)(page),每個(gè)頁(yè)當(dāng)中存儲(chǔ)了用戶數(shù)據(jù),所有的頁(yè)合在一起組成了一顆B+樹(shù);

頁(yè) 是InnoDB存儲(chǔ)引擎管理數(shù)據(jù)庫(kù)的最小磁盤(pán)單位,我們常說(shuō)每個(gè)節(jié)點(diǎn)16KB,其實(shí)就是指每頁(yè)的大小為16KB。
這16KB的空間,里面需要存儲(chǔ) 頁(yè)格式 信息和 行格式 信息,其中行格式信息當(dāng)中又包含一些元數(shù)據(jù)和用戶數(shù)據(jù)。所以我們?cè)谟?jì)算的時(shí)候,要把這些數(shù)據(jù)的都計(jì)算在內(nèi)。
你的mysql到底能存多少數(shù)據(jù)呢?

下邊具體介紹下啥是頁(yè)格式和行格式;

注意:如果你不明白,那么就不要硬去理解,先去看后邊的計(jì)算環(huán)節(jié),結(jié)合計(jì)算再來(lái)一點(diǎn)點(diǎn)看這些介紹,因?yàn)楹筮叺挠?jì)算用到的數(shù)據(jù)都要出自這里的介紹。

頁(yè)格式

每一頁(yè)的基本格式,也就是每一頁(yè)都會(huì)包含的一些信息,總結(jié)表格如下:
你的mysql到底能存多少數(shù)據(jù)呢?

另外,當(dāng)新記錄插入到 InnoDB 聚集索引中時(shí),InnoDB 會(huì)嘗試留出 1/16 的頁(yè)面空閑以供將來(lái)插入和更新索引記錄。如果按順序(升序或降序)插入索引記錄,則生成的頁(yè)大約可用 15/16 的空間。如果以隨機(jī)順序插入記錄,則頁(yè)大約可用 1/2 到 15/16 的空間。

除了 User Records和Free Space 以外所占用的內(nèi)存是 38+56+26+8=128字節(jié),每一頁(yè)留給用戶數(shù)據(jù)的空間就還剩 16 × 15/16 × 1024?128=15232字節(jié)(保留了1/16)。
當(dāng)然,這是最小值,因?yàn)槲覀儧](méi)有考慮頁(yè)目錄。頁(yè)目錄留在后面根據(jù)再去考慮,這個(gè)得根據(jù)表字段來(lái)計(jì)算。

重點(diǎn)是頁(yè)目錄,下邊計(jì)算會(huì)取一個(gè)平均值,根據(jù)圖上說(shuō)的是每個(gè)槽(不用管啥是槽)會(huì)放4~8條,取平均值就是6條,一個(gè)槽會(huì)占用2byte(取最大值吧)。

行格式

首先,我覺(jué)得有必要提一嘴,MySQL5.6的默認(rèn)行格式為COMPACT(緊湊),5.7及以后的默認(rèn)行格式為DYNAMIC(動(dòng)態(tài)),不同的行格式存儲(chǔ)的方式也是有區(qū)別的,還有其他的兩種行格式,本文后續(xù)的內(nèi)容主要是基于DYNAMIC(動(dòng)態(tài))進(jìn)行講解的。(了解即可)

特性對(duì)比(了解即可):

  • DYNAMIC(動(dòng)態(tài)):
    當(dāng)使用 DYNAMIC 創(chuàng)建表時(shí),InnoDB 會(huì)將較長(zhǎng)的可變長(zhǎng)度列(比如 VARCHAR、VARBINARY、BLOB 和 TEXT 類型)的值剝離出來(lái),存儲(chǔ)到一個(gè)溢出頁(yè)上,只在該列上保留一個(gè) 20 字節(jié)的指針指向溢出頁(yè)。

    優(yōu)點(diǎn)
    DYNAMIC 行格式避免了用大量數(shù)據(jù)填充 B+ 樹(shù)節(jié)點(diǎn)從而導(dǎo)致長(zhǎng)列的問(wèn)題。
    DYNAMIC 行格式的想法是,如果長(zhǎng)數(shù)據(jù)值的一部分存儲(chǔ)在頁(yè)外,則通常將整個(gè)值存儲(chǔ)在頁(yè)外是最有效的。
    使用 DYNAMIC 格式,較短的列會(huì)盡可能保留在 B+ 樹(shù)節(jié)點(diǎn)中,從而最大限度地減少給定行所需的溢出頁(yè)數(shù)。

  • COMPACT(緊湊):
    將前 768 個(gè)字節(jié)和 20 字節(jié)的指針存儲(chǔ)在 B+ 樹(shù)節(jié)點(diǎn)的記錄中,其余部分存儲(chǔ)在溢出頁(yè)上。

    列是否存儲(chǔ)在頁(yè)外取決于頁(yè)大小和行的總大小。當(dāng)一行太長(zhǎng)時(shí),選擇最長(zhǎng)的列進(jìn)行頁(yè)外存儲(chǔ),直到聚集索引記錄適合 B+ 樹(shù)頁(yè)(文檔里沒(méi)說(shuō)具體是多少??)。小于或等于 40 字節(jié)的 TEXT 和 BLOB 直接存儲(chǔ)在行內(nèi),不會(huì)分頁(yè)。

言歸正傳:每一行的基本格式,總結(jié)表格如下:
你的mysql到底能存多少數(shù)據(jù)呢?
重點(diǎn)是事務(wù)ID和指針字段、行記錄頭信息 ,計(jì)算的時(shí)候要用,因?yàn)楣潭ǖ闹狄惨闵稀?/strong>

字符編碼不同情況下的存儲(chǔ)(重要)

char 、varchar、text 等需要設(shè)置字符編碼的類型,在計(jì)算所占用空間時(shí),需要考慮不同編碼所占用的空間。

  • varchar、text等類型會(huì)有長(zhǎng)度字段列表來(lái)記錄他們所占用的長(zhǎng)度,但char是固定長(zhǎng)度的類型,情況比較特殊,假設(shè)字段 name 的類型為 char(10) ,則有以下情況:
  • 對(duì)于長(zhǎng)度固定的字符編碼(比如ASCII碼),字段 name 將以固定長(zhǎng)度格式存儲(chǔ),ASCII碼每個(gè)字符占一個(gè)字節(jié),那 name 就是占用 10 個(gè)字節(jié)。
  • 對(duì)于長(zhǎng)度不固定的字符編碼(比如utf8mb4),至少將為 name 保留 10 個(gè)字節(jié)。如果可以,InnoDB會(huì)通過(guò)修剪尾部空格空間的方式來(lái)將其存到 10 個(gè)字節(jié)中。
    如果空格剪完了還存不下,則將尾隨空格修剪為 列值字節(jié)長(zhǎng)度的最小值(一般是 1 字節(jié))。
    列的最大長(zhǎng)度為: 字符編碼的最大字符長(zhǎng)度×N,比如 name 字段的編碼為 utf8mb4,那就是 4×10。
  • 大于或等于 768 字節(jié)的 char 列會(huì)被看成是可變長(zhǎng)度字段(就像varchar一樣),可以跨頁(yè)存儲(chǔ)。例如,utf8mb4 字符集的最大字節(jié)長(zhǎng)度為 4,則 char(255) 列將可能會(huì)超過(guò) 768 個(gè)字節(jié),進(jìn)行跨頁(yè)存儲(chǔ)。

總結(jié)一下:

字符編碼不同,字段所占用的字節(jié)也會(huì)不同,固定字符編碼(比如ASCII碼)就是寫(xiě)多少就是多少,char(10),就占用10個(gè)字節(jié),不固定的(比如utf8mb4)超過(guò)10個(gè)字節(jié)就用字符編碼的最大字符長(zhǎng)度(utf8mb4的這個(gè)值是4,結(jié)尾的mb4就代表4個(gè)字節(jié),這個(gè)可以自己去查)x N,那么char(20)占用字節(jié)=4 x 20 =80,如果結(jié)果大于768,那么就會(huì)跨頁(yè)存儲(chǔ)(知道就行)。

計(jì)算

計(jì)算InnoDB的3層B+樹(shù)最多可以存多少條數(shù)據(jù)
計(jì)算之前,先回顧一下前邊的東西,頁(yè)格式和行格式;
存儲(chǔ)總量 = 可變數(shù)據(jù) + 固定數(shù)據(jù);
可變數(shù)據(jù)就是我們實(shí)際要存儲(chǔ)的數(shù)據(jù),固定數(shù)據(jù)就是內(nèi)置好的數(shù)據(jù),從上邊的兩個(gè)表格就能看到了。

通過(guò)頁(yè)格式的介紹,我們知道,刨除固定數(shù)據(jù)量之后,我們得到的剩余存儲(chǔ)空間是15232字節(jié)

那么,我們開(kāi)始計(jì)算不固定的數(shù)據(jù)量,也就是我們要存儲(chǔ)的實(shí)際信息,這個(gè)就只能舉例說(shuō)明了。

  • 簡(jiǎn)單一例:

先計(jì)算單個(gè)節(jié)點(diǎn)的:
假設(shè)我們的主鍵id為 bigint 型,也就是8個(gè)字節(jié);
那索引頁(yè)中每行數(shù)據(jù)占用的空間就等于 8 + 6(事物ID[上表有寫(xiě)]) + 5(行記錄頭) = 19 字節(jié)。
每頁(yè)可以存 15232 ÷ 19 ≈ 801 條索引數(shù)據(jù)。
那算上頁(yè)目錄的話,按每個(gè)槽平均6條數(shù)據(jù)計(jì)算的話,至少有 801 ÷ 6 ≈ 134 個(gè)槽,需要占用 268 字節(jié)的空間。
所以最終的結(jié)果是(15232-268)÷ 19 ≈ 787條索引數(shù)據(jù);
三層的數(shù)據(jù)量:
三層的葉子節(jié)點(diǎn)就是7872(反正就是這么算的,不用管,記住公式),也就是787x787= 619369 個(gè)葉子節(jié)點(diǎn),每個(gè)節(jié)點(diǎn)可以存儲(chǔ)787條數(shù)據(jù),最終能存儲(chǔ) 787 x 619369 = (自己算)條數(shù)據(jù)。
主鍵為 int 的表可以存放 993 ^ 2 = 986049 個(gè)葉子節(jié)點(diǎn),下邊會(huì)用。

  • 簡(jiǎn)單二例:

– 這是一張非常普通的課程安排表,除id外,僅包含了課程id和老師id兩個(gè)字段
– 且這幾個(gè)字段均為 int (4個(gè)字節(jié))型(當(dāng)然實(shí)際生產(chǎn)中不會(huì)這么設(shè)計(jì)表,這里只是舉例)。
CREATE TABLE course_schedule (
id int NOT NULL,
teacher_id int NOT NULL,
course_id int NOT NULL,
PRIMARY KEY (id) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

每行數(shù)據(jù)所占用的空間就是 4 + 4 + 4 + 6 + 7 + 5 = 30 字節(jié),每個(gè)葉子節(jié)點(diǎn)可以存放 15232÷30≈507條數(shù)據(jù)。
頁(yè)目錄占用空間:507 ÷ 685 x 2 = 170字節(jié)
算上頁(yè)目錄的槽位所占空間,每個(gè)葉子節(jié)點(diǎn)可以存放 (15232 - 170) ÷ 30502 條數(shù)據(jù);
那么三層B+樹(shù)可以存放的最大數(shù)據(jù)量就是 502×986049(主鍵是int)=494,996,將近5億條數(shù)據(jù)!
  • 常規(guī)一例:

CREATE TABLE blog (
id bigint unsigned NOT NULL AUTO_INCREMENT COMMENT ‘博客id’,
author_id bigint unsigned NOT NULL COMMENT ‘作者id’,
title varchar(50) CHARACTER SET utf8mb4 NOT NULL COMMENT ‘標(biāo)題’,
description varchar(250) CHARACTER SET utf8mb4 NOT NULL COMMENT ‘描述’,
school_code bigint unsigned DEFAULT NULL COMMENT ‘院校代碼’,
cover_image char(32) DEFAULT NULL COMMENT ‘封面圖’,
create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT ‘創(chuàng)建時(shí)間’,
release_time datetime DEFAULT NULL COMMENT ‘首次發(fā)表時(shí)間’,
modified_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT ‘修改時(shí)間’,
status tinyint unsigned NOT NULL COMMENT ‘發(fā)表狀態(tài)’,
is_delete tinyint unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (id),
KEY author_id (author_id),
KEY school_code (school_code) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_general_mysql500_ci ROW_FORMAT=DYNAMIC;

1、行記錄頭信息:肯定得有,占用5字節(jié)。
2、可變長(zhǎng)度字段列表:表中 title占用1字節(jié),description占用2字節(jié)(雖然看著沒(méi)超過(guò)255,但是用的是utf8mb4編碼,所以實(shí)際是255 x 4,所以占用兩個(gè)字節(jié)),共3字節(jié)。
3、null值列表:表中僅school_code、cover_image、release_time3個(gè)字段可為null,故僅占用1字節(jié)。
4、事務(wù)ID和指針字段:兩個(gè)都得有,占用13字節(jié)。
5、字段內(nèi)容信息:

  • id、author_id、school_code 均為bigint型,各占用8字節(jié),共24字節(jié)。
  • create_time、release_time、modified_time 均為datetime類型,各占8字節(jié),共24字節(jié)。
  • status、is_delete 為tinyint類型,各占用1字節(jié),共2字節(jié)。
  • cover_image 為char(32),字符編碼為表默認(rèn)值utf8,由于該字段實(shí)際存的內(nèi)容僅為英文字母(存url的),結(jié)合前面講的字符編碼不同情況下的存儲(chǔ) ,故僅占用32字節(jié)。
  • title、description 分別為varchar(50)、varchar(250),這兩個(gè)應(yīng)該都不會(huì)產(chǎn)生溢出頁(yè)(不太確定),字符編碼均為utf8mb4,實(shí)際生產(chǎn)中70%以上都是存的中文(3字節(jié)),25%為英文(1字節(jié)),還有5%為4字節(jié)的表情,則存滿的情況下將占用:
    (50 + 250) × ( 0.7 × 3 + 0.25 × 1 + 0.05 × 4) = 765 字節(jié)。
統(tǒng)計(jì)上面的所有分析,共占用 869 字節(jié),則每個(gè)葉子節(jié)點(diǎn)可以存放 15232 ÷869≈17條,算上頁(yè)目錄,仍然能放 17 條。
則三層B+樹(shù)可以存放的最大數(shù)據(jù)量就是 17 × 619369(根據(jù)主鍵是bigint) = 10,529,27317,約一千萬(wàn)條數(shù)據(jù)

你的mysql到底能存多少數(shù)據(jù)呢?文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-428600.html

到了這里,關(guān)于你的mysql到底能存多少數(shù)據(jù)呢?的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包