2014-04-24 27 views
0

我已經在MySQL下表:MySQL表的大小不匹配我的計算

CREATE TABLE `ParaTable` (
    `id_1` INT(10) UNSIGNED NULL DEFAULT '0', 
    `id_2` INT(10) UNSIGNED NULL DEFAULT '0', 
    `id_3` TINYINT(3) UNSIGNED NULL DEFAULT '0', 
    `id_4` TINYINT(3) UNSIGNED NULL DEFAULT '0', 
    `id_5` INT(10) UNSIGNED NULL DEFAULT '0', 
    `date` TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP, 
    INDEX `id_1` (`id_1`), 
    INDEX `id_2` (`id_2`), 
    INDEX `date` (`date`), 
    INDEX `id_3` (`id_3`), 
    INDEX `id_4` (`id_4`), 
    INDEX `id_5` (`id_5`), 
    INDEX `multi_index` (`id_1`, `id_3`, `id_4`) 
) 
COLLATE='utf8_general_ci' 
ENGINE=InnoDB; 

它有大約7000萬項的總數,即使列是空的,沒有一個項目有一個NULL在任何列(這裏的表結構不是問題)。

如果我考慮information_schema,我可以看到,索引長度爲10272899072和數據長度是3201302528.

這使得共12,850MB的,或約12.54GB。

這個數字是如何計算的?

SHOW TABLE STATUS ... LIKE ParaTable顯示輸出:

Rows: 68129609 
Avg_row_length: 47 
Data_length: 3201302528  (=3053MB) 
Index_length: 10272899072  (=9797MB) 

我讀到的數據存儲大小in the MySQL manual,並已提出了以下粗略計算:

(INT + INT + TINYINT + TINYINT + INT +時間戳)

(+ 6位,因爲每列可以爲空,我假設我可以將這6位計算爲另一個字節並且是安全的,請參閱 the manual

4 + 4 + 1 + 1 + 4 + 4 = =每行19個字節。

(即使每個6位的取盤,這是不可能的我猜1個字節,這將是每行24個字節)。

18 bytes * 70,000,000 rows = 1260000000B = ~1200MB 
(19 bytes * 70,000,000 rows = 1330000000B = ~1270MB) 
(24 bytes * 70,000,000 rows = 1680000000B = ~1600MB) 

我不知道有多少空間MySQL的需要爲索引(我只能從SHOW TABLES的值,但它是如何計算的?)。這是計算所需總尺寸時缺少的一個環節。但即使指數與它沒有任何關係,單靠Data_length似乎也太高了。

爲什麼Avg_row_length 47而不是我計算的18-24字節?我在這裏錯過了什麼?

回答

1

您錯過了計算InnoDB存儲這些行的所有開銷。你應該有:

4 (INT) 
+ 4 (INT) 
+ 1 (TINYINT) 
+ 1 (TINYINT) 
+ 4 (INT) 
+ 4 (TIMESTAMP) 
+ 1 (Null bitmap, rounded up to whole bytes) 
+ 5 (Row header) 
+ 6 (ROW_ID: Implicit cluster key, because you are missing a PRIMARY KEY) 
+ 6 (TRX_ID: Transaction ID) 
+ 7 (ROLL_PTR: Rollback/undo pointer) 
= 43 bytes per row 

然後你還需要考慮頁面填充率(網頁沒有被設計填充100%),其在絕對最低增加約7%:

43 
* 1/(15/16) 
= 45.86 bytes per row 

此外,您將在分配但未使用的空間中有開銷。

所以實際上,每行約47個字節並不差。最糟糕的情況是開銷消耗約50%,導致表格每行約需86字節。

對於每一個次級鍵,注意他們的空間消耗的樣子(使用id_1爲例):

4 (INT) 
+ 1 (Null bitmap, rounded up to whole bytes) 
+ 5 (Row header) 
+ 6 (ROW_ID: Implicit cluster key) 
= 16 bytes per row 
* 1/(15/16) 
= 17.06 bytes per row 

它可閱讀有關InnoDB的數據結構如下職位,以學習有用更多:

+0

嗨,jeremy,謝謝你解釋和鏈接!這現在開始有意義了:D – para