前言
在进行sql进行优化的时候,加了索引,但发现报了一个错,what?这是什么呢?但内心想着,莫慌莫慌,任何事情都有解决的方案的。具体的错误信息如下:
Specified key was too long; max key length is 3072 bytes
这个错误的信息就是,指定的密钥太长,最大密钥长度为3072字节。
问题分析
为什么会出现这个问题,是因为建立索引时,数据库计算key的长度累加所有Index用到的字段的char长度后再按下面比例乘起来不能超过限定的key长度1000;这里科普下关于数据库类型占字节知识,也相当于是不断反复学习了。
字段类型的大小需要根据字符集类型来定,我这里用的是utf8的字符集,一般占3个字节。
可以做如下测试:
从上可得出内存存储上“我们”占用了2字节,而“我们”占用6字节。
这里做下验证,我先将表中数据插满,用了repeat直接插入多条数据,如下所示:
insert into t select 9, repeat('b', 7000), -1;
这当时还有个小插曲,我没有给上面语句的b加上英文符号的’ '这个,导致一直提示说找不到此列,我心想这不是有嘛。害我找了半天。其实主要是因为我插入的是a这个数据,它不是作为列出现的,这个地方我理解错误了。
接下来就查看int(11)可以存多少个数字,答案:是9个
问题解决
说明:上面我的验证只是想看下我这个具体的设置的字段类型和长度到底能存的数据时多少。很明显我这加起来就超过了1000,所以创建索引不成功。
试想将字段b的数据类型也就是varchar(8000)改成varchar(3000)会怎样。答案会报错,如下改成1099都会报错。
这样设置也报错:
当设置成1021就ok了,但注意这个不是但看b字段的长度的,具体怎么加法,具体原因我还没有深究,知道的请告知
那为什么这样就能创建成功呢?这里就涉及到3n+2这样的一个就散,注意这里的3针对的是innoDB引擎存储一个汉字三个字节问题。然后Int类型又是固定的占4个字节。所以只需要用(3n+2)+两个int的占字节的数,不大于3072就行。
由repeat引发的思考
如果想要批量插入几万条数据的话,有什么优化的方法?
总结
很多知识都是需要去不断验证的,不验证不会有损失,但验证你的收获一定不少。