磁碟上表格資料的儲存需求取決於幾個因素。不同的儲存引擎以不同的方式表示資料類型並儲存原始資料。表格資料可能會被壓縮,無論是針對欄位或整列,這都會使計算表格或欄位的儲存需求變得複雜。
儘管磁碟上的儲存佈局有所不同,但溝通和交換表格列資訊的內部 MySQL API 使用一致的資料結構,適用於所有儲存引擎。
本節包含 MySQL 支援的每個資料類型的儲存需求指南和資訊,包括使用固定大小表示資料類型的儲存引擎的內部格式和大小。資訊按類別或儲存引擎列出。
表格的內部表示法最大列大小為 65,535 位元組,即使儲存引擎能夠支援更大的列也是如此。此數字不包括 BLOB 或 TEXT 欄位,它們僅佔此大小的 9 到 12 位元組。對於 BLOB 和 TEXT 資料,資訊會儲存在與列緩衝區不同的記憶體區域中。不同的儲存引擎根據它們用於處理對應類型的方法,以不同的方式處理此資料的配置和儲存。有關更多資訊,請參閱第 18 章,替代儲存引擎和第 10.4.7 節,「表格欄位計數和列大小的限制」。
NDB 表格使用4 位元組對齊;所有 NDB 資料儲存都是以 4 位元組的倍數進行的。因此,通常需要 15 位元組的欄位值在 NDB 表格中需要 16 位元組。例如,在 NDB 表格中,TINYINT、SMALLINT、MEDIUMINT 和 INTEGER (INT) 欄位類型由於對齊因素,每個記錄都需要 4 位元組的儲存空間。
每個 BIT( 欄位佔用 M)M 位元的儲存空間。儘管單個 BIT 欄位不是 4 位元組對齊的,NDB 會為 BIT 欄位所需的前 1-32 位保留每列 4 個位元組(32 位元),然後為位元 33-64 保留另 4 個位元組,依此類推。
雖然 NULL 本身不需要任何儲存空間,但如果表格定義包含任何允許 NULL 的欄位,NDB 會為每列保留 4 個位元組,最多 32 個 NULL 欄位。(如果 NDB 叢集表格定義了超過 32 個 NULL 欄位,最多 64 個 NULL 欄位,則每列保留 8 個位元組。)
每個使用 NDB 儲存引擎的表格都需要主鍵;如果您沒有定義主鍵,NDB 會建立一個「隱藏」主鍵。這個隱藏的主鍵每個表格記錄會消耗 31-35 位元組。
您可以使用 ndb_size.pl Perl 腳本來估計 NDB 的儲存需求。它會連線到目前的 MySQL (非 NDB Cluster) 資料庫,並建立一份關於該資料庫若使用 NDB 儲存引擎時所需空間的報告。請參閱 第 25.5.29 節,「ndb_size.pl — NDBCLUSTER 大小需求估算器」 以取得更多資訊。
| 資料類型 | 所需儲存空間 |
|---|---|
TINYINT |
1 位元組 |
SMALLINT |
2 位元組 |
MEDIUMINT |
3 位元組 |
INT、INTEGER |
4 位元組 |
BIGINT |
8 位元組 |
FLOAT( |
若 0 <= p <= 24,則為 4 位元組;若 25 <= p <= 53,則為 8 位元組 |
FLOAT |
4 位元組 |
DOUBLE [PRECISION]、REAL |
8 位元組 |
DECIMAL(、NUMERIC( |
不固定;請參閱後續討論 |
BIT( |
大約 (M+7)/8 位元組 |
DECIMAL(和 NUMERIC)欄位的值使用二進位格式表示,該格式將九個十進位(以 10 為基底)數字壓縮成四個位元組。每個值的整數部分和小數部分的儲存空間是分開決定的。每九位數需要四個位元組,而「剩餘」的數字則需要四個位元組的某個部分。剩餘數字所需的儲存空間由下表提供。
| 剩餘數字 | 位元組數 |
|---|---|
| 0 | 0 |
| 1 | 1 |
| 2 | 1 |
| 3 | 2 |
| 4 | 2 |
| 5 | 3 |
| 6 | 3 |
| 7 | 4 |
| 8 | 4 |
對於 TIME、DATETIME 和 TIMESTAMP 欄位,MySQL 5.6.4 之前建立的表格與 5.6.4 或之後建立的表格所需的儲存空間不同。這是因為 5.6.4 的變更允許這些類型具有小數部分,這需要 0 到 3 個位元組。
| 資料類型 | MySQL 5.6.4 之前的所需儲存空間 | 自 MySQL 5.6.4 起的所需儲存空間 |
|---|---|---|
YEAR |
1 位元組 | 1 位元組 |
DATE |
3 位元組 | 3 位元組 |
TIME |
3 位元組 | 3 位元組 + 小數秒儲存空間 |
DATETIME |
8 位元組 | 5 位元組 + 小數秒儲存空間 |
TIMESTAMP |
4 位元組 | 4 位元組 + 小數秒儲存空間 |
自 MySQL 5.6.4 起,YEAR 和 DATE 的儲存空間保持不變。然而,TIME、DATETIME 和 TIMESTAMP 的表示方式不同。DATETIME 的壓縮效率更高,非小數部分需要 5 個而不是 8 個位元組,而且這三個部分都有一個小數部分,這需要 0 到 3 個位元組,具體取決於儲存值的小數秒精度。
| 小數秒精度 | 所需儲存空間 |
|---|---|
| 0 | 0 位元組 |
| 1, 2 | 1 位元組 |
| 3, 4 | 2 位元組 |
| 5, 6 | 3 位元組 |
例如,TIME(0)、TIME(2)、TIME(4) 和 TIME(6) 分別使用 3、4、5 和 6 個位元組。TIME 和 TIME(0) 是等效的,並且需要相同的儲存空間。
有關時間值內部表示的詳細資訊,請參閱 MySQL 內部:重要演算法和結構。
在下表中,M 代表非二進位字串類型的宣告欄位長度(以字元為單位),以及二進位字串類型的宣告欄位長度(以位元組為單位)。L 代表給定字串值的實際長度(以位元組為單位)。
| 資料類型 | 所需儲存空間 |
|---|---|
CHAR( |
InnoDB 列格式的精簡系列優化了可變長度字元集的儲存。請參閱 精簡列格式儲存特性。否則,M × w 位元組,其中 <= 255,而 w 是字元集中最大長度字元所需的位元組數。 |
BINARY( |
M 位元組,0 <= 255 |
VARCHAR(、VARBINARY( |
如果欄位值需要 0 到 255 個位元組,則為 L + 1 個位元組;如果值可能需要超過 255 個位元組,則為 L + 2 個位元組 |
TINYBLOB、TINYTEXT |
L + 1 個位元組,其中 L < 28 |
BLOB、TEXT |
L + 2 個位元組,其中 L < 216 |
MEDIUMBLOB、MEDIUMTEXT |
L + 3 個位元組,其中 L < 224 |
LONGBLOB、LONGTEXT |
L + 4 個位元組,其中 L < 232 |
ENUM(' |
1 或 2 個位元組,具體取決於列舉值的數量(最多 65,535 個值) |
SET(' |
1、2、3、4 或 8 個位元組,具體取決於設定成員的數量(最多 64 個成員) |
可變長度字串類型使用長度前置詞加上資料儲存。長度前置詞需要一到四個位元組,具體取決於資料類型,而前置詞的值為 L(字串的位元組長度)。例如,儲存 MEDIUMTEXT 值需要 L 個位元組來儲存該值,外加三個位元組來儲存該值的長度。
若要計算用於儲存特定 CHAR、VARCHAR 或 TEXT 欄位值的位元組數,您必須考慮該欄位所使用的字元集,以及該值是否包含多位元組字元。特別是,當使用 UTF-8 Unicode 字元集時,您必須記住,並非所有字元都使用相同數量的位元組。utf8mb3 和 utf8mb4 字元集可能分別需要每個字元最多三個和四個位元組。有關不同類別的 utf8mb3 或 utf8mb4 字元所使用儲存空間的詳細資訊,請參閱 第 12.9 節,「Unicode 支援」。
VARCHAR、VARBINARY 以及 BLOB 和 TEXT 類型都是可變長度類型。對於每種類型,儲存需求都取決於以下因素:
欄位值的實際長度
欄位的最大可能長度
欄位所使用的字元集,因為某些字元集包含多位元組字元
例如,一個 VARCHAR(255) 資料行可以容納最大長度為 255 個字元的字串。假設該資料行使用 latin1 字元集(每個字元一個位元組),實際所需的儲存空間為字串的長度(L),再加上一個位元組來記錄字串的長度。對於字串 'abcd',L 為 4,儲存需求為五個位元組。如果相同的資料行改為宣告使用 ucs2 雙位元組字元集,則儲存需求為 10 個位元組:'abcd' 的長度為八個位元組,且該資料行需要兩個位元組來儲存長度,因為最大長度大於 255(最多 510 個位元組)。
可以儲存在 VARCHAR 或 VARBINARY 資料行中的有效最大位元組數會受到最大資料列大小 65,535 位元組的限制,該限制在所有資料行之間共享。對於儲存多位元組字元的 VARCHAR 資料行,有效最大字元數會較少。例如,utf8mb4 字元每個字元最多可能需要四個位元組,因此使用 utf8mb4 字元集的 VARCHAR 資料行可以宣告為最大 16,383 個字元。請參閱第 10.4.7 節「資料表資料行計數和資料列大小的限制」。
InnoDB 將長度大於或等於 768 個位元組的固定長度欄位編碼為可變長度欄位,這些欄位可以儲存在頁面之外。例如,如果字元集的最大位元組長度大於 3,則 CHAR(255) 資料行可能會超過 768 個位元組,例如 utf8mb4。
NDB 儲存引擎支援可變寬度資料行。這表示 NDB Cluster 資料表中的 VARCHAR 資料行所需的儲存空間與任何其他儲存引擎相同,但例外的是此類值會以 4 位元組對齊。因此,使用 latin1 字元集儲存在 VARCHAR(50) 資料行中的字串 'abcd' 需要 8 個位元組(而不是 MyISAM 資料表中相同資料行值的 5 個位元組)。
TEXT、BLOB 和 JSON 資料行在 NDB 儲存引擎中的實作方式不同,其中資料行中的每個資料列都由兩個獨立的部分組成。其中一個是固定大小的(對於 TEXT 和 BLOB 為 256 個位元組,對於 JSON 為 4000 個位元組),並且實際上儲存在原始資料表中。另一個則包含超過 256 個位元組的任何資料,這些資料儲存在隱藏的 blob 部分資料表中。此第二個資料表中資料列的大小取決於資料行的確切類型,如下表所示
| 類型 | Blob 部分大小 |
|---|---|
BLOB、TEXT |
2000 |
MEDIUMBLOB、MEDIUMTEXT |
4000 |
LONGBLOB、LONGTEXT |
13948 |
JSON |
8100 |
這表示如果 size <= 256(其中 size 代表資料列的大小),則 TEXT 資料行的大小為 256;否則,大小為 256 + size + (2000 × (size − 256) % 2000)。
對於 TINYBLOB 或 TINYTEXT 資料行值,NDB 不會單獨儲存 blob 部分。
您可以使用資料行註解中的 NDB_COLUMN,在建立或修改父資料表時,將 NDB blob 資料行的 blob 部分大小增加到最大值 13948。NDB 也支援使用資料行註解中的 NDB_TABLE,設定 TEXT、BLOB 或 JSON 資料行的內嵌大小。如需更多資訊,請參閱NDB_COLUMN 選項。
ENUM 物件的大小取決於不同列舉值的數量。對於最多 255 個可能值的列舉,使用一個位元組。對於具有 256 到 65,535 個可能值的列舉,使用兩個位元組。請參閱第 13.3.6 節「ENUM 類型」。
SET 物件的大小取決於不同集合成員的數量。如果集合大小為 N,則物件佔用 ( 個位元組,向上捨入到 1、2、3、4 或 8 個位元組。N+7)/8SET 最多可以有 64 個成員。請參閱第 13.3.7 節「SET 類型」。
MySQL 使用 4 個位元組來指示 SRID,然後使用值的 WKB 表示法來儲存幾何值。LENGTH() 函數會傳回儲存值所需的空間(以位元組為單位)。
如需空間值的 WKB 和內部儲存格式的描述,請參閱第 13.4.3 節「支援的空間資料格式」。
一般而言,JSON 資料行的儲存需求與 LONGBLOB 或 LONGTEXT 資料行的儲存需求大致相同;也就是說,JSON 文件所消耗的空間與該文件的字串表示儲存在這些類型之一的資料行中所消耗的空間大致相同。但是,二進位編碼會造成額外的負擔,包括中繼資料和用於查閱的字典,這些資料和字典是儲存在 JSON 文件中的個別值所需要的。例如,儲存在 JSON 文件中的字串需要額外 4 到 10 個位元組的儲存空間,具體取決於字串的長度以及儲存該字串的物件或陣列的大小。
此外,MySQL 對儲存在 JSON 資料行中的任何 JSON 文件的大小施加限制,使其不得大於 max_allowed_packet 的值。