[转]MySQL InnoDB引擎索引长度受限怎么办

mysql> CREATE TABLE `tb` (
-> `a` varchar(255) DEFAULT NULL,
-> `b` varchar(255) DEFAULT NULL,
-> `c` varchar(255) DEFAULT NULL,
-> `d` varchar(255) DEFAULT NULL,
-> `e` varchar(255) DEFAULT NULL,
-> KEY `a` (`a`,`b`,`c`,`d`,`e`)
-> ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes
能够看到,因为每一个字段占用255*3, 所以这个索引的大小是3825>3072,报错。
为何3072
咱们知道InnoDB一个page的默认大小是16k。因为是Btree组织,要求叶子节点上一个page至少要包含两条记录(不然就退化链表了)。
因此一个记录最多不能超过8k。
又因为InnoDB的聚簇索引结构,一个二级索引要包含主键索引,所以每一个单个索引不能超过4k (极端状况,pk和某个二级索引都达到这个限制)。
因为须要预留和辅助空间,扣掉后不能超过3500,取个“整数”就是(1024*3)。
单列索引限制

上面有提到单列索引限制767,原由是256×3-1。这个3是字符最大占用空间(utf8)。可是在5.5之后,开始支持4个字节的uutf8。255×4>767, 因而增长了一个参数叫作 innodb_large_prefix。
这个参数默认值是OFF。当改成ON时,容许列索引最大达到3072。
能够看到默认行为是建表成功,报一个warning,而且将长度阶段为255。
注意要生效须要加row_format=compressed或者dynamic 。
若是确实须要在单个很大的列上建立索引,或者须要在多个很大的列上建立联合索引,而又超过了索引的长度限制,解决办法是在建索引时限制索引prefix的大小:
例如:create index yarn_app_result_i4 on yarn_app_result (flow_exec_id(100), another_column(50));
这样,在建立索引时就会限制使用的每一个列的最大长度。如上的例子中,在建立联合索引时,最多使用列flow_exec_id中前100个字符建立索引,最多使用another_column中前
50个字符建立索引。这样子,就能够避免索引长度过大的问题。

最后,我想说一句。咱们在设计数据库时,最好不要在一个可能包含很长字符串的列上建立索引,尤为是当这个列中的字符串都很长时。若是在这类列上建立了索引,那么在建立索引时以及根据索引查询时,都会浪费不少时间在计算和存储上。有经验的设计人员应该不会这样设计数据库。mysql

相关文章
相关标签/搜索