大家好,我是程序员。今天给大家分享一个我遇到的比较少见的面试题,那就是MySQL中如何计算索引的长度。说实话,第一次遇到这个问题的时候,我想当然的认为索引长度就是我们建表时定义的字段长度。如果是联合索引,就是多个字段长度相加。原来我说出上面的答案后,面试官就让我拿着简历跑了。于是,仔细查阅了相关资料,发现索引长度的计算方法有点意思,分享给大家。首先,我们要知道MySQLInnodb引擎对索引的长度是有限制的,最多767字节。如果使用不同的字符编码方式,对应的字节数是不同的。比如我们最常用的utf8mb4字符集是4字节字符集,那么767字节/每个字符4字节=191个字符(默认索引是最大长度),所以在varchar(255)或char(255)类型字段会失败,错误消息会指出最大索引长度为767字节。其他编码方式的对应关系是:在latin1编码中,一个字符占一个字节,在gbk编码中,一个字符占两个字节,在utf8编码中,一个字符占三个字节。一般来说,索引长度的计算规则是:对于所有的索引字段,如果不设置NotNull,则需要增加一个字节(这也是我们建表时建议不要有Null字段的原因之一)。对于定长字段,int类型占4个字节,date占3个字节,char(n)占N个字符。对于变量字段varchar(n),即N个字符+两个字节。不同的字符集,一个字符占用的字节数不同。对于latin1编码,一个字符占一个字节,对于gbk编码,一个字符占两个字节,对于utf8编码,一个字符占三个字节。索引长度char(),varchar()索引长度计算公式:CharacterSet:utf8mb4=4,utf8=3,gbk=2,latin1=1)*columnlength+1(Nullallowed)+2(variablelengthcolumn)Based基于以上原则,我们建表验证一下:CREATETABLE`tb_item`(`id`bigintNOTNULLCOMMENT'书的id,也就是书号',`title`varchar(100)NOTNULLCOMMENT'书名',`sell_point`varchar(500)DEFAULTNULLCOMMENT'图书卖点',`price`bigintNOTNULLCOMMENT'书价美分',`num`intNOTNULLCOMMENT'库存数量',`barcode`varchar(30)DEFAULTNULLCOMMENT'书本条码',`image`varchar(500)DEFAULTNULLCOMMENT'书本图片',`cid`bigintNOTNULLCOMMENT'类别,叶类',`status`tinyintNOTNULLDEFAULT'1'COMMENT'图书状态,1-正常,2-下架,3-删除',`created`datetimeNOTNULLCOMMENT'创建时间',`updated`datetimeNOTNULLCOMMENT'更新时间',`upload_id`bigintDEFAULTNULL,PRIMARYKEY(`id`),KEY`cid`(`cid`),KEY`status`(`status`),KEY`updated`(`updated`),KEY`tb_item_title_price_num`(`title`,`price`,`num`))ENGINE=InnoDBDEFAULTCHARSET=utf8COMMENT='booktable';在这张表上我们创建了一个联合索引tb_item_title_price_num由三个字段组成,即变长字段varchar、定长字段price和num。我们先执行如下语句:explainselect*fromtb_itemwheretitle='编译原理'andprice=45andnum=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。为了验证我们的计算方法,我们接着执行如下语句使索引部分失效。解释一下select*fromtb_itemwheretitle='编译原理'andnum=23232因为我们跳过了price字段,所以在联合索引中只有title字段生效,其余无效。如果我们的计算方法没有问题,那么此时执行计划中的key_len应该是302。果然,我们看到key_len变成了302,说明index部分失效了,只有title字段index起作用了。同时Extra是Usingindex条件,表示使用了索引,但是需要回表查询数据。explainexecutionplan中其他字段的具体含义可以参考这篇文章。好了,今天的内容就到这里。简单总结一下,在MySQL中,索引长度不仅取决于我们在建表时设置的字段长度,还与具体的字符集编码、字段是否允许为Null等多种条件有关。字段长度只能用作索引长度的预测。估计值,而不是确切值。我是程序员,稀饭,关注我,我们一起在技术的海洋中向上成长。
