一直有傳 言 說,MySQL 表的數據只要超過 20 00 萬行,其性能就會下降。而本文作者用實驗分析證明:至少在 2023 年 ,這已不再是 MySQL 表的有效軟限制。

原文 鏈接:https://yishenggong.com/2023/05/22/is-20m-of-rows-still-a-valid-soft-limit-of-mysql-table-in-2023/

未經允許,禁止轉載!


(資料圖片)

作 者 | Yisheng Gong 譯者 | 彎月 責編 | 鄭麗媛 出品 | CSDN(ID:CSDNnews)

傳言

互聯網上有一則傳言說,我們應該避免單個 MySQL 表中的數據超過 2000 萬行,否則表的性能就會下降——當數據量超過這個軟限制時,你就會發現 SQL 的查詢速度會比平時慢很多。 這 是 多年前 針 對 H DD 做出的 判斷 。 我 想知道,時至 2 023 年, SSD 上的 MySQL 是 否 仍然 有 此 限制 。 如果 真 的有,那么原因是什么呢?

環境

數據庫

? MySQL 版本: 8.0.25

? 實例類型:AWS db.r5.large(2vCPUs, 16GiB RAM)

? EBS 存儲類型:General Purpose SSD(gp2)

測試客戶端

? Linux 內核版本:6.1

? 實例類型:AWS t2.micro(1 vCPU, 1GiB RAM)

實驗設計

創建具有相同結構、但大小不同的表。我一共創建了 9 個表,數據行數分別為:10 萬、20 萬、50 萬、100 萬、200 萬、500 萬、1000 萬、2000 萬、3000 萬、5000 萬和 6000 萬。

1. 創建幾個具有相同結構的表:

CREATE TABLE row_test(`id` int NOT  AUTO_INCREMENT,`person_id` int NOT ,`person_name` VARCHAR(200),`insert_time` int,`update_time` int,PRIMARY KEY (`id`),KEY `query_by_update_time` (`update_time`),KEY `query_by_insert_time` (`insert_time`));

2. 插入不同的數據。我使用了測試客戶端和表復制的方式創建了這些表。腳本可參考:https://github.com/gongyisheng/playground/blob/main/mysql/row_test/insert_data.py。

# test clientINSERT INTO {table} (person_id, person_name, insert_time, update_time) VALUES ({person_id}, {person_name}, {insert_time}, {update_time})# copycreate table like insert into (`person_id`, `person_name`, `insert_time`, `update_time`)select `person_id`, `person_name`, `insert_time`, `update_time` from

person_id、person_name、insert_time 和 update_time 的值是隨機的。

3. 使用測試客戶端執行以下 sql 查詢來測試性能。腳本可參考:https://github.com/gongyisheng/playground/blob/main/mysql/row_test/select_test.py。

select count(*) from 
-- full table scanselect count(*) from
where id = 12345 -- query by primary keyselect count(*) from
where insert_time = 12345 -- query by indexselect * from
where insert_time = 12345 -- query by index, but cause 2-times index tree lookup

4. 查看 innodb 緩沖池狀態。

SHOW ENGINE INNODB STATUSSHOW STATUS LIKE "innodb_buffer_pool_page%

5. 每次完成表的測試,請務必重新啟動數據庫!刷新 innodb 緩沖池,避免讀取舊緩存,得到錯誤的結果!

結果

查詢1:select count(*) from

這種查詢會執行全表掃描,MySQL 并 不擅長這種工作。

? 第一輪:沒有緩存。第一次執行查 詢時,緩沖池中沒有緩存數據。

? 第二輪:有緩存。當緩沖池中已經有數據緩存時執行查詢,通常在第一次查詢執行完之后。

觀察結果:

1. 第一輪查詢的執行時 間超出了后面幾次。

原因是 MySQL 使用了 innodb_buffer_pool 來緩存數據頁。在第一次執行查詢之前,緩沖池是空的,所以 MySQL 必 須進行大量的磁盤 I/O 才能從 .idb 文件加載表。但在第一次執行結束后,緩沖池中存儲了數據,后續查詢可以直接讀取內存,避免磁盤 I/O,因此速度更快。該過程稱為 MySQL 緩沖池預熱。

2. select count(*) from

會設法將整個表加載到緩沖池。

我比較了實驗前后 innodb_buffer_po ol 的統計數據。運行查詢后,如果緩沖池足夠大,則其使用量變化等于表的大小。否則,只有部分表會緩存在緩沖池中。原因是查詢 select count(*) from table 會做全表掃描,并做逐行統計。如果沒有緩存,就需要將完整的表加載到內存中。為什么?因為 Innodb 支持事務,它不能保證事務在不同時間看到同一張表。全表掃描是獲得準確行數的唯一安全方法。

3. 如果緩沖池不能容納全表,則 會爆發查詢延遲。

我注意到 innodb_buffer_pool 的大小 會極大地影響查詢性能,因此我嘗試在不同的配置下運行查詢。當使用 11G 緩沖區,而表的大小達到 5000 萬行時,就會爆發查詢延遲。接著,我將緩沖區縮減到 7G,當表的大小達到 3000 萬行時,爆發了查詢延遲。最后,我將緩沖區縮減到 3G,當表的大小僅為 2000 萬行時,就爆發了查詢延遲。很明顯,如果表中的數據無法緩存在緩沖池中,則 select count(*) from

必須執行昂貴的磁盤 I/O,這會導致查詢運行時間直線上升。

4. 對于沒有緩存的查詢,查詢花 費的時間與表的大小呈線性關系,與緩沖池大小無關。

當沒有緩存時,查詢花費的時間 由磁盤 I/O 決定,與緩沖池大小無關。在 IOPS 相同的情況下,是否使用 select count(*) 預熱緩沖池并沒有區別。

5. 如果無法完整地緩存整個表,則有無緩存的查詢運行時間差異是恒定的。

另請注意,如果無法完整地緩存整個表,雖然查詢運行時會突然上升,但運行時是可預測的。無論表的大小如何,有無緩存的時間差異是恒定的。原因是表的部分數據緩存在緩沖區中,這里的時間差異來自從緩沖區讀取數據節省的時間。

查詢2,3:select count(*) from

where = 12345

這個查詢使用了索引。由于不是范圍查詢,MySQL 只需要利用 B+ 樹的路徑從上到下查找頁面,并將這些頁面緩存 到 innodb 緩沖池中即可。

我創建的表的 B+ 樹的深度都是 3,因此前面的 3~4 次 I/O 都被拿來預熱緩沖區,平均耗時 4~6 毫秒。之后,再次運行相同的查詢,MySQL 就會直接從內存中查找結果,耗時為 0.5 毫秒,約等于網絡 RTT。如果緩存頁面長時間未命中,并從緩沖池中逐出,則必須再次從磁盤加載該頁面,這樣就需要磁盤 I/O(最多 4 次)。

查詢4:select * from

where = 12345

這個查詢涉及兩次索引查找。由于 select * 需要查詢獲取的 person_name、person_id 字段并不在索引中, 因此在查 詢執行期間,數據庫引擎必須查找 2 個 B+ 樹。它首先查找 insert_time B+ 樹,獲取目標行的主鍵,然后查找主鍵 B+ 樹,獲取該行的完整數據,如下圖所示:

這就是我們應該在生產中避免 select * 的 原因。 此次實驗證實,此查詢加載的頁面塊比查詢 2 或 3 多出了 2 倍, 且最高可達 8 倍。查詢的平均運行時間為 6~10 毫秒,也是查詢 2 或 3 的 1.5~2 倍。

傳言是怎么來的

首先,我們需要知道 innodb 索引頁的物理結 構。默認頁面大小為 16k,由頁眉、系統記錄、用戶記錄、頁面導向器和尾部組成。只有剩下的 14~15k 用來存儲數據。

假設你使用 INT 作為主鍵(4 字節),每行 1KB 的有效負載。每個葉頁可以存儲 15 行,一個指向該頁的指針需要 4+8=12 字節。因此,每個非葉頁最多可以容納 15k / 12 字節 = 1280 個指針。如果你有一個 4 層的 B+ 樹,它最多可以容納 1280*1280*15 = 24.6M 行數據。

回到 HDD 占據市場主導地位,且 SSD 對于數據庫而言過于昂貴的時代,4 次隨機 I/O 可能是我們可以容忍的最壞情況,而使用 2 次索引樹查找的查詢甚至會使情況變得更糟。當時的工程師想要控制索引樹的深度,不希望它們太深。而如今 SSD 越來越流行,隨機 I/O 比以前便宜了,因此我們應該反思一下 10 年前的規則。

順便說一句,5 層 B+ 樹可以容納 1280*1280*1280*15 = 31.4B 行數據,超過了 INT 所能容納的最大數據量。對每行大小的不同假設將導致不同的軟限制,或小于或大于 2000 萬行。例如,在我的實驗中,每一行大約是 816 字節(我使用 utf8mb4 字符集,所以每個字符占用 4 個字節),4 層 B+ 樹可以容納的軟限制是 29.5M。

結論

? Innodb 緩存池的大小、表的大小決定了是否會出現性能降級。

? 判斷是否需要拆分 MySQL 表的一個更有意義的指標是查詢運行時/緩沖池命中率。如果查詢總是命中緩沖區,則不會有任何性能問題。2000 萬行只是一個經驗值。

? 除了拆分 MySQL 表之外,增加 Innodb 緩存池的大小和數據庫的內存也是一個選擇。

? 如果可能,請避免在生產中使用 select *,這類語句在最壞的情況下會導致 2 次索引樹查找。

? (我個人的意見)考慮到 SSD 現在越來越流行,2000 萬行不再是 MySQL 表的有效軟限制。

標簽:

精彩要聞

新聞推送

日本道免费精品一区二区三区| 久操av在线| 成人在线二区| 日韩欧美电影在线观看| 精品国产乱码| 亚洲色图都市小说| 最新av在线| 国产日韩在线不卡| 免费精品国产| 区一区二日本| 99re热这里只有精品免费视频 | 欧美国产另类| 国产精品的网站| 黄网在线观看| 尹人成人综合网| 欧美xxxx老人做受| 日韩网站中文字幕| 欧洲亚洲视频| 久久久亚洲精品石原莉奈| 乡村艳史在线观看| 一区二区激情视频| 最新av在线播放| 丁香婷婷深情五月亚洲| 国产黄a三级三级三级av在线看| 国产精品美女久久久久| 另类天堂av| a视频v在线| av成人国产| 亚洲国产一区二区三区青草影视| 国产日韩综合| 日本在线成人| 黑巨人与欧美精品一区| 成人看片黄a免费看在线| 久九九久频精品短视频| 亚洲黄色av一区| 国产成人久久| 亚洲区欧美区| 亚洲人精选亚洲人成在线| 一级毛片免费观看| 成人va天堂| 老司机免费视频一区二区| 精品欧美一区二区三区精品久久 | 久久午夜剧场| 欧美日韩国内| 日本特黄a级高清免费大片| 久久这里只有| 欧美日韩精品欧美日韩精品| 超碰国产在线| 国产精品视频看| 99视频有精品高清视频| 欧美日本在线观看| 日韩国产精品久久| 激情图片在线观看高清国产| 久久久久久久久久久电影| 日本三级韩国三级欧美三级| 美女视频黄久久| 你懂得在线网址| 97se亚洲国产综合自在线| 在线观看h片| 国产麻豆综合| 日韩欧美激情四射| 久久免费精品视频在这里| 伪装者在线观看完整版免费| 亚洲精品国产精品乱码不99按摩| 亚洲欧美成aⅴ人在线观看| 激情欧美一区二区三区在线观看| 在线视频观看日韩| 精品三级久久久| 免费黄网站在线| 色综合久久久久综合体| 欧美日韩第一| 精品国产一区二区三区四区阿崩| 91在线视频免费91| h片在线观看网站| 性做久久久久久免费观看| 在线综合视频| 真不卡电影网| 91丨九色丨蝌蚪富婆spa| 日日夜夜精品| 日本在线视频www鲁啊鲁| 亚洲欧美制服丝袜| 久久久99久久精品欧美| 欧美激情视频一区二区三区在线播放 | 亚洲欧美综合精品久久成人| 日韩欧美国产午夜精品| 日本最新在线视频| 欧美另类亚洲| 欧美日韩美少妇| 免费在线看黄| 麻豆精品一区二区av白丝在线| 色综合久久中文字幕综合网| 中文字幕日韩高清在线| 国产精品入口麻豆原神| 国产偷倩在线播放| 欧美午夜女人视频在线| 岛国精品在线观看| 久久福利影院| av影视在线| 欧美日韩在线播放三区| 精品一区欧美| 日韩欧美在线不卡| 精品综合久久88少妇激情| 成人免费看视频网站| 中文字幕第一区二区| 一区二区电影网| 国产一区二区三区视频在线播放| 青青草97国产精品免费观看 | 麻豆传媒在线完整视频| 成人精品国产福利| 久操国产精品| 成人免费看片| 国产精品成人一区二区艾草 | 欧美群妇大交群中文字幕| 国内久久精品| 免费在线你懂的| 狠狠色噜噜狠狠狠狠97| 亚洲九九爱视频| 久久久青草青青国产亚洲免观| 亚洲丁香日韩| 在线国产中文字幕| 91精品国产一区二区三区 | 精品国产乱码久久久久久久久| 国产精品国产三级国产普通话三级| 另类av一区二区| 青青草97国产精品麻豆| 亚洲成人在线| 日韩国产成人精品| 99精品视频中文字幕| 视频在线亚洲| 欧洲亚洲视频| 一区二区三区在线观看免费| 国产一区二区三区探花| 91嫩草国产线观看亚洲一区二区 | 国产精品美女久久久久aⅴ| 国产一区二区0| 国产精品精品| 天堂成人娱乐在线视频免费播放网站| 亚洲激情久久| 自拍偷拍欧美视频| 亚洲精品成人av| 午夜欧美一区二区三区在线播放| 国产麻豆日韩欧美久久| 国产精一品亚洲二区在线视频| 亚洲六月丁香色婷婷综合久久| 欧美在线不卡一区| 成人黄色电影在线| 青春草在线免费视频| 成人在线超碰| 亚洲免费婷婷| 国产a精品视频| 国产精一区二区三区| 国产乱码一区二区三区| 国产乱子伦视频一区二区三区| 91精品国产成人观看| 亚洲国产合集| 国产中文精品久高清在线不| 唐人社导航福利精品| 三上悠亚激情av一区二区三区 | 国产精品日韩精品在线播放| 黄网站app在线观看| av网站免费| 精品国产乱码久久久久久蜜臀| 日韩精品不卡一区二区| 成人免费直播在线| 久久国产精品免费精品3p| 久久综合99| 免费看欧美女人艹b| 极品尤物久久久av免费看| 日本不卡免费在线视频| 久久99精品视频| 成人激情文学综合网| 天堂午夜影视日韩欧美一区二区| 欧美激情视频一区二区三区免费| 粉嫩av一区二区三区| 色网在线观看| 成年人在线观看| 一区二区电影免费观看| 日韩精品永久网址| 首页综合国产亚洲丝袜| 黑人精品xxx一区| 日韩深夜视频| 日韩一区精品| 毛片基地黄久久久久久天堂| 亚洲激情在线| 国产一区二区伦理| 亚洲午夜久久久久久久久电影院 | 日韩毛片免费观看| 国产大片一区| 三级影片在线观看欧美日韩一区二区 | 亚洲人成网站免费播放| 一区二区三区中文字幕精品精品| 17c精品麻豆一区二区免费| 欧美日韩一区二区在线播放| 亚洲高清一区二| 男人添女人下部高潮视频在线观看| 亚洲91视频| 7777精品伊人久久久大香线蕉 | 成人污污视频在线观看| 91精品国产一区二区三区香蕉 | 日韩午夜激情免费电影|

          <thead id="kigni"></thead>
          <source id="kigni"></source>