2000萬數據與性能急劇下降
業務流傳着這樣的觀點,當單表數據量超過2000萬時,性能會急劇下降。我曾在職業生涯中經歷過單表數據量超過2000萬的情況,性能是否下降至無法接受的程度,其實也並非如此,查詢效率還取決於服務器的硬件情況,網絡帶寬等其他因素,至於與單表數據量百萬級十萬級比較時,確實會出現較為明顯的差異。
為什麼是2000萬
頁與數據量
探討這個問題,需要先對MySql的索引,B+樹,InnoDb的頁結構有基礎的認知,可移步閲讀,此處不作詳述。
InnoDb的頁(節點)大小默認是16kb,假設表的主鍵是bigint型,長度8字節,InnoDb的源碼中,指針大小設置為6字節,一共14字節,則非葉子節點的每一頁可存放16kb/14字節約等於1170個主鍵(+指針)。
樹與數據量
假設單條數據大小為1kb,主鍵為bigint型
當樹高為2層時
可存儲的數據量為 1170 * 16 / 1(根節點存放1170個指針,第二層全部為葉子節點存放數據,每一個頁可存16條數據)
當樹高為3層時
可存儲的數據量為 1170 1170 16 / 1(根節點存放1170個指針,第二層共1170個非葉子節點,每個節點存放1170個指針,第三層為葉子節點,沒頁可存16條數據)
可得出在樹高為3層時,大約可存放2190萬數據。而當主鍵為int型時,3層樹高可存放更多的數據,而當超過這個數據量,層高達到4時,查詢的效率就會下降,也就是業界流傳數據量與性能下降的閾值來源。
實際情況
select concat(table_schema,'.',table_name) as name,
concat(Round(data_length/(1024),6),'kb') as data_size,
concat(Round(index_length/(1024),6),'kb') as index_size
from information_schema.tables
where table_schema like '%%'
通過table_schema來查看數據行大小,通常情況下單條數據大小並未達到1kb,因此單頁數據量實際上大於16條,此外實際性能還受到硬件和網絡因素影響,閾值並非絕對的2000萬