1.什么是前缀索引?所谓前缀索引,说白了就是对文本的前几个字符建立索引(具体是建立索引时指定的几个字符),比如商品名称的前10个字符用于构建索引,使得构建的索引更小。查询效率更快!有点类似于Oracle中在字段上使用Left函数创建函数式索引,只不过MySQL的前缀索引在查询时会自动在内部完成匹配,不需要使用Left函数。二、为什么要用前缀索引?有的同学可能会问,为什么不索引整个字段呢?一般来说,当某个字段的数据量过大,查询非常频繁时,使用前缀索引可以有效的减小索引文件的大??小,让每个索引页可以保存更多的索引值,从而提高索引查询速度。比如,有的客户店名很长,有的很短。如果按照全覆盖建立索引,索引的存储空间可能会非常大。对于一些表,如果创建的索引很多,索引存储空间甚至会比数据表的存储空间大很多。因此,对于这么长的文本字段,我们可以截取前几个字符来建立索引。在一定程度上,既能满足数据的查询效率要求,又能节省Index存储空间。但另一方面,前缀索引也有其缺点。在MySQL中,前缀索引不能用于ORDERBY和GROUPBY,也不能用于覆盖扫描。当字符串本身可能比较长,而前几个字符是完全一样的时候,这时候前缀索引的优势就不再明显了,也就没有必要再创建前缀索引了。那么这又回到了一个概念,那就是关于索引的选择性!关于数据库表索引的选择性,我会另开一章来讲解。你只需要记住一件事:索引的选择性越高,查询效率就越高,因为选择性高的索引可以让MySQL在查找的时候过滤掉更多。行,数据查询速度更快!当某个字段内容的前几位差异化程度很高时,此时使用前缀索引可以在查询性能和空间存储方面达到??很高的性价比。那么问题来了,如何创建前缀索引呢?3、如何创建前缀索引?建立前缀索引的方法很简单,按照下面的方式就可以建立!ALTERTABLEtable_nameADDKEY(column_name(prefix_length));其中,参数prefix_length表示前缀长度,通常通过以下方法确认。步骤如下:首先,先计算某个字段所有列的判别值。SELECTCOUNT(DISTINCTcolumn_name)/COUNT(*)FROMtable_name;第二步,然后计算前缀的长度,最相似的是整列的判别SELECTCOUNT(DISTINCTLEFT(column_name,prefix_length))/COUNT(*)FROMtable_name;最后不断调整prefix_length的值,直到和计算出的整列判别值相近,最接近的值就是我们想要的值。我们以一张测试表为例,数据量超过100万,表结构如下!CREATETABLE`tb_test`(`id`bigint(20)unsignedNOTNULLAUTO_INCREMENT,`name`varchar(100)DEFAULTNULL,PRIMARYKEY(`id`))ENGINE=InnoDBAUTO_INCREMENT=1DEFAULTCHARSET=utf8mb4;testnormal带有name条件的查询效率如下:select*fromtb_testwherenamelike'1805.59281427%'我们以name字段为例,创建一个前缀索引,找到最合适的prefix_length值。首先我们粗略计算一下name字段整列的判别度。可以看到结果是0.9945,也就是说全局不同数据率为99.45%。下面我们来看一下,在不同的prefix_length取值下,对应的数据不重复的比例。当prefix_length为5时,区分度为0.2237当prefix_length为10时,区分度为0.9944当prefix_length为11时,区分度为0.9945通过对比,我们发现当prefix_length为11时,是最接近全局判别度,所以可以为name创建长度为11的前缀索引。索引创建语句如下:altertabletb_testaddkey(name(11));接下来我们再试试上面的语句查询!创建前缀索引后,查询效率翻倍!4、使用前缀索引需要注意什么?是否所有字段都适合前缀索引?答案显然不是。上面我们提到,当一个索引的string列很大时,创建的索引也会变得很大。为了减小索引的大小,提高索引的扫描速度,将字符串的前面部分作为索引值,这样索引占用的空间会大大减少,索引的选择性不会减少很多。这时候前缀索引的作用就会非常明显。前缀索引的本质是索引查询性能和存储空间。一种平衡。对于BLOB和TEXT列或非常长的VARCHAR列的索引,您必须使用前缀索引,因为MySQL不允许索引它们的全长。但是,如果某个字段的内容,比如前缀部分,相似度很高,此时前缀索引的效果就不会很明显,使用覆盖索引的效果会更好!5.总结好了,本文主要围绕前缀索引做一个初步的知识讲解。具体数据库表索引的选择性需要结合业务的实际需求来考虑!今天就说到这里,剩下的问题我们继续聊!
