MYSQL行與列限制

1、列數量限制

mysql官網可知每個數據表限制列數量爲4096,官網也說了一般比這個更小,取決於以下幾個因素:

  • 最大行大小會影響表的列數,因爲總的列長度不能超過該大小
  • 存儲引擎、字符集、排列方式、存儲格式也有一定的影響
  • 功能性的key也會有影響,比如索引就會生成一個隱含的虛擬列,其他也是如此,對列數量也有一定限制

2、行大小限制

  • mysql內部機制允許每一個表有一個最大的行大小爲65535字節,即使有些存儲引擎支持比這個更大的行大小;BLOB和TEXT列一般只會有9~12個字節用於行大小,因爲他的其他內容和該行不存儲在同一個地方
    *** InnoDb**存儲引擎則不同,他一般只和innodb_page_size參數相關,一般會稍微小於該值的一半,比如,對於16KB頁大小,最大行大小<=8KB這也是innodb的默認頁大小
  • 如果該行包含可變列而且超過最大行大小,那麼innodb將會把那些超過不分放到外部頁外存儲

3、例子(來源於官網)

1、驗證行大小65536

mysql> select version();
+-----------+
| version() |
+-----------+
| 8.0.15    |
+-----------+
1 row in set (0.01 sec)

mysql> CREATE TABLE t (a VARCHAR(10000), b VARCHAR(10000),
       c VARCHAR(10000), d VARCHAR(10000), e VARCHAR(10000),
       f VARCHAR(10000), g VARCHAR(6000)) ENGINE=InnoDB CHARACTER SET latin1;
1118 - Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs
mysql> CREATE TABLE t (a VARCHAR(10000), b VARCHAR(10000),
       c VARCHAR(10000), d VARCHAR(10000), e VARCHAR(10000),
       f VARCHAR(10000), g VARCHAR(6000)) ENGINE=MyISAM CHARACTER SET latin1;
1118 - Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs

該限制是強制性的,與存儲引擎無關即使存儲引擎支持更大的行大小。

2、BLOB和TEXT

將上述例子其中一列修改爲BLOB或者TEXT試試?

mysql> CREATE TABLE t (a VARCHAR(10000), b VARCHAR(10000),
       c VARCHAR(10000), d VARCHAR(10000), e VARCHAR(10000),
       f VARCHAR(10000), g TEXT(6000)) ENGINE=MyISAM CHARACTER SET latin1;
Query OK, 0 rows affected (0.08 sec)

mysql> CREATE TABLE t1 (a VARCHAR(10000), b VARCHAR(10000),
       c VARCHAR(10000), d VARCHAR(10000), e VARCHAR(10000),
       f VARCHAR(10000), g TEXT(6000)) ENGINE=InnoDB CHARACTER SET latin1;
Query OK, 0 rows affected (0.50 sec)

可以看出即使看起來超過最大行大小(65535)字節,依然能創建成功。對於MyISAM:BLOB/TEXT只會佔用9~12字節,而對於Innodb則會使用外部頁外存儲

3、對於那些可變列存儲需要話費額外的長度字節,這也會計算到行大小,例如 VARCHAR(255) CHARACTER SET utf8mb3將會使用2個字節標識該值長度,所以每個值將會達到767字節(255*3(utfmb3佔用3字節存儲)+2)

因此以下創建語句將會成功,因爲他剛好達到65535字節(32765 + 2+32766 + 2)

mysql> CREATE TABLE t1
       (c1 VARCHAR(32765) NOT NULL, c2 VARCHAR(32766) NOT NULL)
       ENGINE = InnoDB CHARACTER SET latin1;
Query OK, 0 rows affected (0.45 sec)

同理下面t2表將會失敗

mysql> CREATE TABLE t2
       (c1 VARCHAR(65535) NOT NULL)
       ENGINE = InnoDB CHARACTER SET latin1;
1118 - Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs
mysql> CREATE TABLE t2
       (c1 VARCHAR(65533) NOT NULL)
       ENGINE = InnoDB CHARACTER SET latin1;
Query OK, 0 rows affected (0.36 sec)

4、對於MyISAM存儲引擎,NULL值列將會需要額外的空間作爲判斷該值是否爲空,一般是一個bit,四捨五入最近的一個字節中

下面的t3將會創建失敗,因爲對於NULL列需要額外的空間,將會超過65536字節

mysql> CREATE TABLE t3
       (c1 VARCHAR(32765) NULL, c2 VARCHAR(32766) NULL)
       ENGINE = MyISAM CHARACTER SET latin1;
1118 - Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs

5、InnoDB行大小取決於innodb_page_size(默認16KB),一般爲該值的一般,但是64KB是,最大行大小<=16KB而不是<=32KB

mysql> select @@innodb_page_size/1024;
+-------------------------+
| @@innodb_page_size/1024 |
+-------------------------+
| 16.0000                 |
+-------------------------+
1 row in set (0.02 sec)

mysql> CREATE TABLE t4 (
       c1 CHAR(255),c2 CHAR(255),c3 CHAR(255),
       c4 CHAR(255),c5 CHAR(255),c6 CHAR(255),
       c7 CHAR(255),c8 CHAR(255),c9 CHAR(255),
       c10 CHAR(255),c11 CHAR(255),c12 CHAR(255),
       c13 CHAR(255),c14 CHAR(255),c15 CHAR(255),
       c16 CHAR(255),c17 CHAR(255),c18 CHAR(255),
       c19 CHAR(255),c20 CHAR(255),c21 CHAR(255),
       c22 CHAR(255),c23 CHAR(255),c24 CHAR(255),
       c25 CHAR(255),c26 CHAR(255),c27 CHAR(255),
       c28 CHAR(255),c29 CHAR(255),c30 CHAR(255),
       c31 CHAR(255),c32 CHAR(255),c33 CHAR(255)
       ) ENGINE=InnoDB ROW_FORMAT=DYNAMIC DEFAULT CHARSET latin1;
1118 - Row size too large (> 8126). Changing some columns to TEXT or BLOB may help. In current row format, BLOB prefix of 0 bytes is stored inline.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章