文本字段越长,在这个字段上建索引的代价就越高

方法1:可以为这个字段配一个hash字段,然后在这个hash字段上建索引。

select * from log where url_hash= CRC32('http://bing.com?query=xxx&tp=xxx' )

crc32()返回的值一般比较短,比较合适; 如果用md5或sha1做hash, 返回的值也很长,那就失去意义了。不过,像上面这样写可能存在hash collision问题,所以应该加个原字段上的搜索条件,确保搜出来的是自己想要的:

select * from log where url_hash= CRC32('http://bing.com?query=xxx&tp=xxx' ) and url = ''http://bing.com?query=xxx&tp=xxx'

方法2:前缀索引

假设现在表User 中存在email字段,为长字符串

alter table User add index index2(email(6));

前缀索引占用的空间更小,但是会增加扫描的次数。
使用前缀索引,定义好长度,就可以做到既节省空间,又不额外增加太多查询成本。
在建立索引时关注选择,可区分度越高,意味着重复的索引越少

  • 索引的选择性:是指不重复的索引值(也称基数)和数据表的记录总数(#T)的比值,范围从1/#T到1之间。索引的选择性越高则查询效率越高,因为选择性高的索引可以让MySQL在查找时过滤更多的行。唯一索引的选择性是1,这是最好的索引选择性,性能也是最好的。例如:select 1.0*count(distinct name)/count(*) from test这是比较整个name的重复率,当时这是最好的情况。然后分别截取name字符的前几个字母,最后选取的计算值要接近整个取整个name时得出的计算值,然后再选中占用空间小的
  • 索引树结构是由表记录数和索引大小确定的,设表的记录数是N,每一个B+树节点平均有B个索引,则树高为logNB,因此对不唯一的属性值建立索引,重复值应该会同时出现在索引中,叶子结点会按索引大小(所有属性值,包括重复)进行排序,索引与对应记录键值存放在一起。故前缀索引选择度不高时,重复的索引就越多(链表连接),对应键值越多,扫描聚簇索(聚簇索引只有一个)引次数就越多