主頁 > 資料庫 > MySQL最大建議行數2000W?老司機做了個實驗……

MySQL最大建議行數2000W?老司機做了個實驗……

2023-01-05 07:36:30 資料庫

 

 

一、背景

 

作為在后端圈開車的多年老司機,是不是經常聽到過,“mysql 單表最好不要超過 2000w”,“單表超過 2000w 就要考慮資料遷移了”,“你這個表資料都馬上要到 2000w 了,難怪查詢速度慢”,

 

這些名言民語就和“群里只討論技術,不開車,開車速度不要超過 120 碼,否則自動踢群”,只聽過,沒試過,哈哈,

 

下面我們就把車速踩到底,干到 180 碼試試…….

 

二、實驗

 

實驗一把看看……建一張表:

CREATE TABLE person(
id int NOT NULL AUTO_INCREMENT PRIMARY KEY comment '主鍵',
person_id tinyint not null comment '用戶id',
person_name VARCHAR(200) comment '用戶名稱',
gmt_create datetime comment '創建時間',
gmt_modified datetime comment '修改時間'
) comment '人員資訊表';

 

插入一條資料:

insert into person values(1,1,'user_1', NOW(), now());
 

利用 mysql 偽列 rownum 設定偽列起始點為 1

select (@i:=@i+1) as rownum, person_name from person, (select @i:=100) as init;
set @i=1;

 

運行下面的 sql,連續執行 20 次,就是 2 的 20 次方約等于 100w 的資料;執行 23 次就是 2 的 23 次方約等于 800w , 如此下去即可實作千萬測驗資料的插入,如果不想翻倍翻倍的增加資料,而是想少量,少量的增加,有個技巧,就是在 SQL 的后面增加 where 條件,如 id > 某一個值去控制增加的資料量即可,

insert into person(id, person_id, person_name, gmt_create, gmt_modified)

select @i:=@i+1,

left(rand()*10,10) as person_id,

concat('user_',@i%2048),

date_add(gmt_create,interval + @i*cast(rand()*100 as signed) SECOND),

date_add(date_add(gmt_modified,interval +@i*cast(rand()*100 as signed) SECOND), interval + cast(rand()*1000000 as signed) SECOND)

from person;

 

此處需要注意的是,也許你在執行到近 800w 或者 1000w 資料的時候,會報錯:The total number of locks exceeds the lock table size,這是由于你的臨時表記憶體設定的不夠大,只需要擴大一下設定引數即可,

SET GLOBAL tmp_table_size =512*1024*1024; (512M)
SET global innodb_buffer_pool_size= 1*1024*1024*1024 (1G);

 

先來看一組測驗資料,這組資料是在 mysql 8.0 的版本,并且是在我本機上,由于本機還跑著 idea , 瀏覽器等各種工具,所以并不是機器配置就是用于資料庫配置,所以測驗資料只限于參考,

 

圖片

 

圖片

 

看到這組資料似乎好像真的和標題對應,當資料達到 2000w 以后,查詢時長急劇上升;難道這就是鐵律嗎?

 

那下面我們就來看看這個建議值 2kw 是怎么來的?

 

三、單表數量限制

 

首先我們先想想資料庫單表行數最大多大?

CREATE TABLE person(
id int(10) NOT NULL AUTO_INCREMENT PRIMARY KEY comment '主鍵',
person_id tinyint not null comment '用戶id',
person_name VARCHAR(200) comment '用戶名稱',
gmt_create datetime comment '創建時間',
gmt_modified datetime comment '修改時間'
) comment '人員資訊表';

看看上面的建表 sql,id 是主鍵,本身就是唯一的,也就是說主鍵的大小可以限制表的上限,如果主鍵宣告 int 大小,也就是 32 位,那么支持 2^32-1 ~~ 21 億;如果是 bigint,那就是 2^62-1 ?(36893488147419103232),難以想象這個的多大了,一般還沒有到這個限制之前,可能資料庫已經爆滿了!!

 

有人統計過,如果建表的時候,自增欄位選擇無符號的 bigint , 那么自增長最大值是 18446744073709551615,按照一秒新增一條記錄的速度,大約什么時候能用完?

 

圖片

 

四、表空間

 

下面我們再來看看索引的結構,對了,我們下面講內容都是基于 Innodb 引擎的,大家都知道 Innodb 的索引內部用的是 B+ 樹

 

圖片

 

這張表資料,在硬碟上存盤也是類似如此的,它實際是放在一個叫 person.ibd (innodb data)的檔案中,也叫做表空間;雖然資料表中,他們看起來是一條連著一條,但是實際上在檔案中它被分成很多小份的資料頁,而且每一份都是 16K,大概就像下面這樣,當然這只是我們抽象出來的,在表空間中還有段、區、組等很多概念,但是我們需要跳出來看,

 

圖片

 

五、頁的資料結構

 

因為每個頁只有 16K 的大小,但是如果資料很多,那一頁肯定就放不下這些資料,那資料肯定就會被分到其他的頁中,所以為了把這些頁關聯起來,肯定就會有記錄前后頁地址,方便找到對應頁;同時每頁都是唯一的,那就會需要有一個唯一標志來標記頁,就是頁號;頁中會記錄資料所以會存在讀寫操作,讀寫操作會存在中斷或者其他例外導致資料不全等,那就會需要有校驗機制,所以里面還有會校驗碼,而讀操作最重要的就是效率問題,如果按照記錄一個個進行遍歷,那肯定是很費勁的,所以這里面還會為資料生成對應的頁目錄(Page Directory); 所以實際頁的內部結構像是下面這樣的,

 

圖片

 

從圖中可以看出,一個 InnoDB 資料頁的存盤空間大致被劃分成了 7 個部分,有的部分占用的位元組數是確定的,有的部分占用的位元組數是不確定的,

 

在頁的 7 個組成部分中,我們自己存盤的記錄會按照我們指定的行格式存盤到 User Records 部分,

 

但是在一開始生成頁的時候,其實并沒有 User Records 這個部分,每當我們插入一條記錄,都會從 Free Space 部分,也就是尚未使用的存盤空間中申請一個記錄大小的空間劃分到 User Records 部分,當 Free Space 部分的空間全部被 User Records 部分替代掉之后,也就意味著這個頁使用完了,如果還有新的記錄插入的話,就需要去申請新的頁了,這個程序的圖示如下,

 

圖片

 

剛剛上面說到了資料的新增的程序,

 

那下面就來說說,資料的查找程序,假如我們需要查找一條記錄,我們可以把表空間中的每一頁都加載到記憶體中,然后對記錄挨個判斷是不是我們想要的,在資料量小的時候,沒啥問題,記憶體也可以撐;但是現實就是這么殘酷,不會給你這個局面;為了解決這問題,mysql 中就有了索引的概念;大家都知道索引能夠加快資料的查詢,那到底是怎么個回事呢?下面我就來看看,

 

六、索引的資料結構

 

在 mysql 中索引的資料結構和剛剛描述的頁幾乎是一模一樣的,而且大小也是 16K, 但是在索引頁中記錄的是頁 (資料頁,索引頁) 的最小主鍵 id 和頁號,以及在索引頁中增加了層級的資訊,從 0 開始往上算,所以頁與頁之間就有了上下層級的概念,

 

圖片

 

看到這個圖之后,是不是有點似曾相似的感覺,是不是像一棵二叉樹啊,對,沒錯!它就是一棵樹,只不過我們在這里只是簡單畫了三個節點,2 層結構的而已,如果資料多了,可能就會擴展到 3 層的樹,這個就是我們常說的 B+ 樹,最下面那一層的 page level =0, 也就是葉子節點,其余都是非葉子節點,

 

圖片

 

看上圖中,我們是單拿一個節點來看,首先它是一個非葉子節點(索引頁),在它的內容區中有 id 和 頁號地址兩部分,這個 id 是對應頁中記錄的最小記錄 id 值,頁號地址是指向對應頁的指標;而資料頁與此幾乎大同小異,區別在于資料頁記錄的是真實的行資料而不是頁地址,而且 id 的也是順序的,

 

七、單表建議值

 

下面我們就以 3 層,2 分叉(實際中是 M 分叉)的圖例來說明一下查找一個行資料的程序,

 

比如說我們需要查找一個 id=6 的行資料,因為在非葉子節點中存放的是頁號和該頁最小的 id,所以我們從頂層開始對比,首先看頁號 10 中的目錄,有 [id=1, 頁號 = 20],[id=5, 頁號 = 30], 說明左側節點最小 id 為 1,右側節點最小 id 是 5;6>5, 那按照二分法查找的規則,肯定就往右側節點繼續查找,找到頁號 30 的節點后,發現這個節點還有子節點(非葉子節點),那就繼續比對,同理,6>5&&6<7, 所以找到了頁號 60,找到頁號 60 之后,發現此節點為葉子節點(資料節點),于是將此頁資料加載至記憶體進行一一對比,結果找到了 id=6 的資料行,

 

從上述的程序中發現,我們為了查找 id=6 的資料,總共查詢了三個頁,如果三個頁都在磁盤中(未提前加載至記憶體),那么最多需要經歷三次的磁盤 IO,

 

需要注意的是,圖中的頁號只是個示例,實際情況下并不是連續的,在磁盤中存盤也不一定是順序的,

 

圖片

 

至此,我們大概已經了解了表的資料是怎么個結構了,也大概知道查詢資料是個怎么的程序了,這樣我們也就能大概估算這樣的結構能存放多少資料了,

 

從上面的圖解我們知道 B+ 數的葉子節點才是存在資料的,而非葉子節點是用來存放索引資料的,

 

所以,同樣一個 16K 的頁,非葉子節點里的每條資料都指向新的頁,而新的頁有兩種可能

 

  • 如果是葉子節點,那么里面就是一行行的資料

  • 如果是非葉子節點的話,那么就會繼續指向新的頁

 

假設

 

  • 非葉子節點內指向其他頁的數量為 x

  • 葉子節點內能容納的資料行數為 y

  • B+ 數的層數為 z

 

如下圖中所示

 

Total =x^(z-1) *y 也就是說總數會等于 x 的 z-1 次方 與 Y 的乘積,

 

圖片

 

X =?

 

在文章的開頭已經介紹了頁的結構,索引也也不例外,都會有 File Header (38 byte)、Page Header (56 Byte)、Infimum + Supermum(26 byte)、File Trailer(8byte), 再加上頁目錄,大概 1k 左右,我們就當做它就是 1K, 那整個頁的大小是 16K, 剩下 15k 用于存資料,在索引頁中主要記錄的是主鍵與頁號,主鍵我們假設是 Bigint (8 byte), 而頁號也是固定的(4Byte), 那么索引頁中的一條資料也就是 12byte; 所以 x=15*1024/12≈1280 行,

 

Y=?

 

葉子節點和非葉子節點的結構是一樣的,同理,能放資料的空間也是 15k;但是葉子節點中存放的是真正的行資料,這個影響的因素就會多很多,比如,欄位的型別,欄位的數量;每行資料占用空間越大,頁中所放的行數量就會越少;這邊我們暫時按一條行資料 1k 來算,那一頁就能存下 15 條,Y≈15,

 

算到這邊了,是不是心里已經有譜了啊

根據上述的公式,Total =x^(z-1) y,已知 x=1280,y=15

假設 B+ 樹是兩層,那就是 Z =2, Total = (1280 ^1 )15 = 19200

假設 B+ 樹是三層,那就是 Z =3, Total = (1280 ^2) *15 = 24576000 (約 2.45kw)

 

哎呀,媽呀!這不是正好就是文章開頭說的最大行數建議值 2000w 嘛!對的,一般 B+ 數的層級最多也就是 3 層,你試想一下,如果是 4 層,除了查詢的時候磁盤 IO 次數會增加,而且這個 Total 值會是多少,大概應該是 3 百多億吧,也不太合理,所以,3 層應該是比較合理的一個值,

 

到這里難道就完了?

 

不,我們剛剛在說 Y 的值時候假設的是 1K ,那比如我實際當行的資料占用空間不是 1K,而是 5K,那么單個資料頁最多只能放下 3 條資料,

 

同樣,還是按照 Z=3 的值來計算,那 Total = (1280 ^2) *3 = 4915200 (近 500w)

 

所以,在保持相同的層級(相似查詢性能)的情況下,在行資料大小不同的情況下,其實這個最大建議值也是不同的,而且影響查詢性能的還有很多其他因素,比如資料庫版本、服務器配置、SQL的撰寫等,MySQL 為了提高性能,會將表的索引裝載到記憶體中,在 InnoDB buffer size 足夠的情況下,其能完成全加載進記憶體,查詢不會有問題,但是,當單表資料庫到達某個量級的上限時,導致記憶體無法存盤其索引,使得之后的 SQL 查詢會產生磁盤 IO,從而導致性能下降,所以增加硬體配置(比如把記憶體當磁盤使),可能會帶來立竿見影的性能提升哈,

 

八、總結

 

  • Mysql 的表資料是以頁的形式存放的,頁在磁盤中不一定是連續的,

 

  • 頁的空間是 16K, 并不是所有的空間都是用來存放資料的,會有一些固定的資訊,如,頁頭,頁尾,頁碼,校驗碼等等,

 

  • 在 B+ 樹中,葉子節點和非葉子節點的資料結構是一樣的,區別在于,葉子節點存放的是實際的行資料,而非葉子節點存放的是主鍵和頁號,

 

  • 索引結構不會影響單表最大行數,2kw 也只是推薦值,超過了這個值可能會導致 B + 樹層級更高,影響查詢性能,

 

>>>>

參考資料

 

  • https://www.jianshu.com/p/cf5d381ef637

  • https://www.modb.pro/db/139052

  • 《MYSQL 內核:INNODB 存盤引擎 卷 1》

 

作者丨京東云開發者

本文來自博客園,作者:古道輕風,轉載請注明原文鏈接:https://www.cnblogs.com/88223100/p/Is-the-maximum-recommended-number-of-MySQL-rows-is-2000W.html

轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/541235.html

標籤:MySQL

上一篇:vivo 實時計算平臺建設實踐

下一篇:大資料 - ADS 資料可視化實作

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • GPU虛擬機創建時間深度優化

    **?桔妹導讀:**GPU虛擬機實體創建速度慢是公有云面臨的普遍問題,由于通常情況下創建虛擬機屬于低頻操作而未引起業界的重視,實際生產中還是存在對GPU實體創建時間有苛刻要求的業務場景。本文將介紹滴滴云在解決該問題時的思路、方法、并展示最終的優化成果。 從公有云服務商那里購買過虛擬主機的資深用戶,一 ......

    uj5u.com 2020-09-10 06:09:13 more
  • 可編程網卡芯片在滴滴云網路的應用實踐

    **?桔妹導讀:**隨著云規模不斷擴大以及業務層面對延遲、帶寬的要求越來越高,采用DPDK 加速網路報文處理的方式在橫向縱向擴展都出現了局限性。可編程芯片成為業界熱點。本文主要講述了可編程網卡芯片在滴滴云網路中的應用實踐,遇到的問題、帶來的收益以及開源社區貢獻。 #1. 資料中心面臨的問題 隨著滴滴 ......

    uj5u.com 2020-09-10 06:10:21 more
  • 滴滴資料通道服務演進之路

    **?桔妹導讀:**滴滴資料通道引擎承載著全公司的資料同步,為下游實時和離線場景提供了必不可少的源資料。隨著任務量的不斷增加,資料通道的整體架構也隨之發生改變。本文介紹了滴滴資料通道的發展歷程,遇到的問題以及今后的規劃。 #1. 背景 資料,對于任何一家互聯網公司來說都是非常重要的資產,公司的大資料 ......

    uj5u.com 2020-09-10 06:11:05 more
  • 滴滴AI Labs斬獲國際機器翻譯大賽中譯英方向世界第三

    **桔妹導讀:**深耕人工智能領域,致力于探索AI讓出行更美好的滴滴AI Labs再次斬獲國際大獎,這次獲獎的專案是什么呢?一起來看看詳細報道吧! 近日,由國際計算語言學協會ACL(The Association for Computational Linguistics)舉辦的世界最具影響力的機器 ......

    uj5u.com 2020-09-10 06:11:29 more
  • MPP (Massively Parallel Processing)大規模并行處理

    1、什么是mpp? MPP (Massively Parallel Processing),即大規模并行處理,在資料庫非共享集群中,每個節點都有獨立的磁盤存盤系統和記憶體系統,業務資料根據資料庫模型和應用特點劃分到各個節點上,每臺資料節點通過專用網路或者商業通用網路互相連接,彼此協同計算,作為整體提供 ......

    uj5u.com 2020-09-10 06:11:41 more
  • 滴滴資料倉庫指標體系建設實踐

    **桔妹導讀:**指標體系是什么?如何使用OSM模型和AARRR模型搭建指標體系?如何統一流程、規范化、工具化管理指標體系?本文會對建設的方法論結合滴滴資料指標體系建設實踐進行解答分析。 #1. 什么是指標體系 ##1.1 指標體系定義 指標體系是將零散單點的具有相互聯系的指標,系統化的組織起來,通 ......

    uj5u.com 2020-09-10 06:12:52 more
  • 單表千萬行資料庫 LIKE 搜索優化手記

    我們經常在資料庫中使用 LIKE 運算子來完成對資料的模糊搜索,LIKE 運算子用于在 WHERE 子句中搜索列中的指定模式。 如果需要查找客戶表中所有姓氏是“張”的資料,可以使用下面的 SQL 陳述句: SELECT * FROM Customer WHERE Name LIKE '張%' 如果需要 ......

    uj5u.com 2020-09-10 06:13:25 more
  • 滴滴Ceph分布式存盤系統優化之鎖優化

    **桔妹導讀:**Ceph是國際知名的開源分布式存盤系統,在工業界和學術界都有著重要的影響。Ceph的架構和演算法設計發表在國際系統領域頂級會議OSDI、SOSP、SC等上。Ceph社區得到Red Hat、SUSE、Intel等大公司的大力支持。Ceph是國際云計算領域應用最廣泛的開源分布式存盤系統, ......

    uj5u.com 2020-09-10 06:14:51 more
  • es~通過ElasticsearchTemplate進行聚合~嵌套聚合

    之前寫過《es~通過ElasticsearchTemplate進行聚合操作》的文章,這一次主要寫一個嵌套的聚合,例如先對sex集合,再對desc聚合,最后再對age求和,共三層嵌套。 Aggregations的部分特性類似于SQL語言中的group by,avg,sum等函式,Aggregation ......

    uj5u.com 2020-09-10 06:14:59 more
  • 爬蟲日志監控 -- Elastc Stack(ELK)部署

    傻瓜式部署,只需替換IP與用戶 導讀: 現ELK四大組件分別為:Elasticsearch(核心)、logstash(處理)、filebeat(采集)、kibana(可視化) 下載均在https://www.elastic.co/cn/downloads/下tar包,各組件版本最好一致,配合fdm會 ......

    uj5u.com 2020-09-10 06:15:05 more
最新发布
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:33:24 more
  • MySQL中binlog備份腳本分享

    關于MySQL的二進制日志(binlog),我們都知道二進制日志(binlog)非常重要,尤其當你需要point to point災難恢復的時侯,所以我們要對其進行備份。關于二進制日志(binlog)的備份,可以基于flush logs方式先切換binlog,然后拷貝&壓縮到到遠程服務器或本地服務器 ......

    uj5u.com 2023-04-20 08:28:06 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:27:27 more
  • 快取與資料庫雙寫一致性幾種策略分析

    本文將對幾種快取與資料庫保證資料一致性的使用方式進行分析。為保證高并發性能,以下分析場景不考慮執行的原子性及加鎖等強一致性要求的場景,僅追求最終一致性。 ......

    uj5u.com 2023-04-20 08:26:48 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:26:35 more
  • 云時代,MySQL到ClickHouse資料同步產品對比推薦

    ClickHouse 在執行分析查詢時的速度優勢很好的彌補了MySQL的不足,但是對于很多開發者和DBA來說,如何將MySQL穩定、高效、簡單的同步到 ClickHouse 卻很困難。本文對比了 NineData、MaterializeMySQL(ClickHouse自帶)、Bifrost 三款產品... ......

    uj5u.com 2023-04-20 08:26:29 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:25:13 more
  • Redis 報”OutOfDirectMemoryError“(堆外記憶體溢位)

    Redis 報錯“OutOfDirectMemoryError(堆外記憶體溢位) ”問題如下: 一、報錯資訊: 使用 Redis 的業務介面 ,產生 OutOfDirectMemoryError(堆外記憶體溢位),如圖: 格式化后的報錯資訊: { "timestamp": "2023-04-17 22: ......

    uj5u.com 2023-04-20 08:24:54 more
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:24:03 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:23:11 more