首页  :: 新随笔  :: 管理

MySQL索引列长度

Posted on 2021-12-24 15:16  高&玉  阅读(2039)  评论(0编辑  收藏  举报

前言

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