前言
MySQL支持的單列索引長度是3072bytes,單列索引長度限制取決於:字段類型、字符集、創建表指定的ROW_FORMA格式。
索引長度計算:
- 索引字段,如果NULL,則需要占用一個字節來記錄值是否為NULL。
- 定長字段,如INT占4個字節、DATE占3個字節、CHAR(N)占N個字符。(注意字符與字節的區別,一個字符占用的字節取決於當前的字符集)
- 變長字段,如VARCHAR(N)占用N個字符+2個字節(記錄長度)。
字符集長度
(root@localhost) [information_schema]> select * from information_schema.CHARACTER_SETS;
+--------------------+----------------------+---------------------------------+--------+
| CHARACTER_SET_NAME | DEFAULT_COLLATE_NAME | DESCRIPTION | MAXLEN |
+--------------------+----------------------+---------------------------------+--------+
| big5 | big5_chinese_ci | Big5 Traditional Chinese | 2 |
| dec8 | dec8_swedish_ci | DEC West European | 1 |
| cp850 | cp850_general_ci | DOS West European | 1 |
| hp8 | hp8_english_ci | HP West European | 1 |
| koi8r | koi8r_general_ci | KOI8-R Relcom Russian | 1 |
| latin1 | latin1_swedish_ci | cp1252 West European | 1 |
| latin2 | latin2_general_ci | ISO 8859-2 Central European | 1 |
| swe7 | swe7_swedish_ci | 7bit Swedish | 1 |
| ascii | ascii_general_ci | US ASCII | 1 |
| ujis | ujis_japanese_ci | EUC-JP Japanese | 3 |
| sjis | sjis_japanese_ci | Shift-JIS Japanese | 2 |
| hebrew | hebrew_general_ci | ISO 8859-8 Hebrew | 1 |
| tis620 | tis620_thai_ci | TIS620 Thai | 1 |
| euckr | euckr_korean_ci | EUC-KR Korean | 2 |
| koi8u | koi8u_general_ci | KOI8-U Ukrainian | 1 |
| gb2312 | gb2312_chinese_ci | GB2312 Simplified Chinese | 2 |
| greek | greek_general_ci | ISO 8859-7 Greek | 1 |
| cp1250 | cp1250_general_ci | Windows Central European | 1 |
| gbk | gbk_chinese_ci | GBK Simplified Chinese | 2 |
| latin5 | latin5_turkish_ci | ISO 8859-9 Turkish | 1 |
| armscii8 | armscii8_general_ci | ARMSCII-8 Armenian | 1 |
| utf8 | utf8_general_ci | UTF-8 Unicode | 3 |
| ucs2 | ucs2_general_ci | UCS-2 Unicode | 2 |
| cp866 | cp866_general_ci | DOS Russian | 1 |
| keybcs2 | keybcs2_general_ci | DOS Kamenicky Czech-Slovak | 1 |
| macce | macce_general_ci | Mac Central European | 1 |
| macroman | macroman_general_ci | Mac West European | 1 |
| cp852 | cp852_general_ci | DOS Central European | 1 |
| latin7 | latin7_general_ci | ISO 8859-13 Baltic | 1 |
| utf8mb4 | utf8mb4_general_ci | UTF-8 Unicode | 4 |
| cp1251 | cp1251_general_ci | Windows Cyrillic | 1 |
| utf16 | utf16_general_ci | UTF-16 Unicode | 4 |
| utf16le | utf16le_general_ci | UTF-16LE Unicode | 4 |
| cp1256 | cp1256_general_ci | Windows Arabic | 1 |
| cp1257 | cp1257_general_ci | Windows Baltic | 1 |
| utf32 | utf32_general_ci | UTF-32 Unicode | 4 |
| binary | binary | Binary pseudo charset | 1 |
| geostd8 | geostd8_general_ci | GEOSTD8 Georgian | 1 |
| cp932 | cp932_japanese_ci | SJIS for Windows Japanese | 2 |
| eucjpms | eucjpms_japanese_ci | UJIS for Windows Japanese | 3 |
| gb18030 | gb18030_chinese_ci | China National Standard GB18030 | 4 |
+--------------------+----------------------+---------------------------------+--------+
創建索引
MySQL 8.X
MySQL 8.X默認支持的單列索引索引最大長度是3072bytes。
數據庫版本:MySQL 8.0.24
字符集:utf8mb4(一個字符占4bytes)
索引字段:變長varchar(n)
創建表
CREATE TABLE `items` (
`itemid` bigint unsigned NOT NULL,
`key_info` varchar(2048) DEFAULT '' NOT NULL,
PRIMARY KEY (itemid)
) ENGINE=InnoDB DEFAULT CHARACTER SET UTF8MB4;
計算支持的最大單列索引長度是(3072-2)/4=767.5
指定索引長度為767
(root@localhost) [test]> CREATE INDEX `index_items_key` ON `items` (`key_info`(767));
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
指定索引長度為768
(root@localhost) [test]> CREATE INDEX `index_items_key` ON `items` (`key_info`(768));
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
指定索引長度為大於768則失敗,報key超過了最大長度
(root@localhost) [test]> CREATE INDEX `index_items_key` ON `items` (`key_info`(769));
ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes
MySQL 5.7
MySQL 5.7默認支持的單列索引索引最大長度是3072bytes,可以通過修改innodb_large_prefix = OFF改變默認支持長度為767bytes。
引用官檔:https://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_file_format
數據庫版本:MySQL 5.7.33
字符集:utf8mb4(一個字符占4bytes)
索引字段:變長字段varchar(n)
創建表
CREATE TABLE `items` (
`itemid` bigint unsigned NOT NULL,
`key_info` varchar(2048) DEFAULT '' NOT NULL,
PRIMARY KEY (itemid)
) ENGINE=InnoDB DEFAULT CHARACTER SET UTF8MB4;
計算支持的最大單列索引長度是(3072-1-2)/4=767.5
指定索引長度為767
(root@localhost) [gaoyu]> CREATE INDEX `index_items_key` ON `items` (`key_info`(767));
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
指定索引長度為768
(root@localhost) [gaoyu]> CREATE INDEX `index_items_key` ON `items` (`key_info`(768));
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
指定索引長度大於768則會失敗
(root@localhost) [gaoyu]> CREATE INDEX `index_items_key` ON `items` (`key_info`(769));
ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes
調整innodb_large_prefix = OFF,則會限制索引單列的最大長度為767bytes。
(root@localhost) [gaoyu]> set @@global.innodb_large_prefix = 0;
Query OK, 0 rows affected, 1 warning (0.00 sec)
計算支持的最大單列索引長度是(767-1-2)/4=191
指定索引長度為191
(root@localhost) [gaoyu]> CREATE INDEX `index_items_key` ON `items` (`key_info`(191));
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
指定索引長度為192 VARCHAR(192)則會失敗
(root@localhost) [gaoyu]> CREATE INDEX `index_items_key` ON `items` (`key_info`(192));
ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes
MySQL 5.6
MySQL 5.6默認支持的單列索引索引最大長度是767bytes,可以通過修改innodb_large_prefix = ON、innodb_file_format = barracuda、innodb_file_per_table = true以及創建表時row_format=(DYNAMIC 或 COMPRESSED)更改默認支持長度為3072bytes。
引用官檔:https://dev.mysql.com/doc/refman/5.6/en/innodb-parameters.html#sysvar_innodb_large_prefix
數據庫版本:MySQL 5.6.21
字符集:utf8mb4(一個字符占4bytes)
索引字段:變長字段varchar(n)
創建表
CREATE TABLE `items` (
`itemid` bigint unsigned NOT NULL,
`key_info` varchar(2048) DEFAULT '' NOT NULL,
PRIMARY KEY (itemid)
) ENGINE=InnoDB DEFAULT CHARACTER SET UTF8MB4;
計算支持的最大單列索引長度是(767-1-2)/4=191
指定索引長度為191
(root@localhost) [gaoyu]> CREATE INDEX `index_items_key` ON `items` (`key_info`(191));
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
指定索引長度為192則失敗
(root@localhost) [gaoyu]> CREATE INDEX `index_items_key` ON `items` (`key_info`(192));
ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes
變更參數,此時支持的索引最大長度是3072bytes
set @@global.innodb_large_prefix = ON;
set @@global.innodb_file_format = barracuda;
set @@global.innodb_file_per_table = true;
重新創建表並指定row_format=DYNAMIC 或 COMPRESSED
CREATE TABLE `items` (
`itemid` bigint unsigned NOT NULL,
`key_info` varchar(2048) DEFAULT '' NOT NULL,
PRIMARY KEY (itemid)
) ENGINE=InnoDB DEFAULT CHARACTER SET UTF8MB4 ROW_FORMAT=DYNAMIC;
計算支持的最大單列索引長度是(3072-1-2)/4=767.5
指定索引長度為767
(root@localhost) [gaoyu]> CREATE INDEX `index_items_key` ON `items` (`key_info`(767));
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
指定索引長度為768
(root@localhost) [gaoyu]> CREATE INDEX `index_items_key` ON `items` (`key_info`(768));
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
索引長度大於768則會失敗
(root@localhost) [gaoyu]> CREATE INDEX `index_items_key` ON `items` (`key_info`(769));
ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes