共计 2293 个字符,预计需要花费 6 分钟才能阅读完成。
大家好,我是程序员啊粥。
明天给大家分享一个我遇到过的比拟少见的面试题,那就是 MySQL 中如何计算一个索引的长度。
说实话,我第一次遇到这个问题的时候想当然的认为索引长度就是咱们建表时定义的字段长度,如果是联结索引,那就是多个字段长度相加。
事实证明,在我说出上述答复之后,面试官就让我带着简历跑路了。
于是乎,我认真查阅了相干材料,发现索引长度这个计算形式还是有点意思的,索性给大家分享一下。
首先,咱们要晓得 MySQL Innodb 引擎对于索引的长度是有限度的,最大为 767 字节。
你采纳不同的字符编码方式,对应的字节数是不一样的,比方咱们最罕用的 utf8mb4 字符集是 4 字节字符集,则 767 字节 / 4 字节每字符 = 191 字符 (默认索引最大长度),所以在 varchar(255) 或 char(255) 类型字段上创立索引会失败,报错会提醒最大索引长度为 767 字节。
其余的一些编码方式对应关系别离是:latin1 编码的,一个字符占用一个字节,gbk 编码的,一个字符占用两个字节,utf8 编码的,一个字符占用三个字节。
总的来说,索引长度计算规定为:
- 所有的索引字段,如果没有设置 Not Null,则须要加一个字节 (这也是咱们为什么倡议建表时不要有 Null 字段的起因之一)。
- 对于定长字段,int 类型占四个字节、date 占三个字节、char(n) 占 N 个字符。
- 对于变成字段 varchar(n),则是 N 个字符 + 两个字节。
- 不同的字符集,一个字符占用的字节数不同。latin1 编码的,一个字符占用一个字节,gbk 编码的,一个字符占用两个字节,utf8 编码的,一个字符占用三个字节。
- 索引长度 char()、varchar() 索引长度的计算公式:
Character Set:utf8mb4=4,utf8=3,gbk=2,latin1=1) * 列长度 + 1(容许 Null) + 2(变长列)
基于以上准则,咱们建张表来验证下:
CREATE TABLE `tb_item` (
`id` bigint NOT NULL COMMENT '书籍 id,同时也是书籍编号',
`title` varchar(100) NOT NULL COMMENT '书籍名称',
`sell_point` varchar(500) DEFAULT NULL COMMENT '书籍卖点',
`price` bigint NOT NULL COMMENT '书籍价格,单位为:分',
`num` int NOT NULL COMMENT '库存数量',
`barcode` varchar(30) DEFAULT NULL COMMENT '书籍条形码',
`image` varchar(500) DEFAULT NULL COMMENT '书籍图片',
`cid` bigint NOT NULL COMMENT '所属类目,叶子类目',
`status` tinyint NOT NULL DEFAULT '1' COMMENT '书籍状态,1- 失常,2- 下架,3- 删除',
`created` datetime NOT NULL COMMENT '创立工夫',
`updated` datetime NOT NULL COMMENT '更新工夫',
`upload_id` bigint DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `cid` (`cid`),
KEY `status` (`status`),
KEY `updated` (`updated`),
KEY `tb_item_title_price_num` (`title`,`price`,`num`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='书籍表';
在这张表上咱们建设了联结索引 tb_item_title_price_num
,由三个字段组成,别离是变长字段 varchar,定长字段 price 以及 num。
咱们先来执行如下这条语句:
explain select * from tb_item where title = '编译原理' and price = 45 and num = 23232
;
咱们看到 key 是 tb_item_title_price_num
,同时索引长度 key_len 为 314,证实是应用到了联结索引 tb_item_title_price_num
的三个残缺字段的。
这个 314 的具体计算形式为:
字符集咱们建表时用的为 utf8 编码,所以 title 字段的索引长度是 3 * 100 + 0 + 2 = 302,price 字段的索引长度是 8,num 字段的索引长度是 4。
因而 tb_item_title_price_num 索引总共长度是 302 + 8 + 4 = 314。
为了验证咱们的计算形式,接下来咱们再执行如下语句,使得索引局部生效。
explain select * from tb_item where title = '编译原理' and num = 23232
这条语句因为咱们跳过了 price 字段,所以联结索引中只会有 title 字段失效,残余局部都会生效,如果咱们计算形式没有问题的话,那么此时执行打算中的 key_len 应该为 302。
果然,咱们看到 key_len 曾经变成了 302,这意味着索引局部生效了,只有 title 字段索引起了作用,同时 Extra 为 Using index condition
,阐明应用了索引,然而须要回表查问数据。
具体 explain 执行打算中其余字段的具体含意,参考这篇文章。
好了,咱们明天的内容就到这里了。
简略总结一下,在 MySQL 中,索引长度不仅取决于咱们建表时设置的字段长度,还和具体的字符集编码以及字段是否容许为 Null 等多个条件相干,字段长度只能作为索引长度的预估项,而不是精确值。
我是程序员啊粥,关注我,咱们一起在技术陆地中向上成长。