MySQL 如何建立合适索引

本文探讨了如何建立合适的数据库索引,尤其是针对字符串字段。前缀索引可以在节省空间的同时牺牲一些查询效率,选择合适的前缀长度需要考虑列的区分度和时间空间平衡。倒序存储和Hash字段是应对特定场景的解决方案,前者适用于尾部有高区分度的字符串,后者通过哈希函数提高查询效率。这两种方法虽不支持范围查询,但在特定情况下能有效优化索引。
摘要由CSDN通过智能技术生成

如何建立合适的索引

什么叫做合适的索引?

笔者认为,在满足基本业务需求的条件下,尽可能的节约索引带来的时间和空间成本,或者是当时间与空间互斥时,选择一种最适合自己的索引方案。其实就是寻找最优解的过程。

字符串字段索引

创建完整索引

将字段完整字符串放进索引。

这种方法简单粗暴,就是有一个弊端:当字符串过长时可能比较占用空间。

创建前缀索引

顾名思义,字符串截取头部一定长度放进索引。

例如有一个邮箱字段 email 其中一行的值为 juneone9@163.com,如果对 email创建前缀索引,指定长度为 8,那么该行在索引中的值就为juneone9

时间换空间

前缀索引是一种以时间换空间的策略。既然减小了索引的长度,势必也会降低索引的区分度,例如 juneone9@qq.comjuneone9@163.comjuneone9@gmail.com这几个值在前缀索引里都为juneone9

执行select id,name,email from t where email= 'juneone9@163.com'; 时,完整索引只需要扫描一行即可得到结果,而前缀索引可能需要增加额外的记录扫描次数,造成时间消耗。

虽然如此,如果能保证截取的前缀依然有足够的区分度,那么将节省大量空间的同时,保证查询的执行效率。这就需要好好把握前缀索引的指定长度。

那么如何选择合适的前缀长度呢?

  • 首先确定需要建立前缀索引列上的区分度,也就是不同值的个数
  • 确定一个可以区分度损失的比例,例如5%。那么就要求前缀索引的区分度要在 (95% * 列总区分度) 以上
  • 查询不同前缀长度的索引区分度
# 查询列总区分度
SELECT
	count( DISTINCT email ) AS L 
FROM t;
	
# 查询不同前缀索引长度的区分度
SELECT
	count( DISTINCT LEFT ( email, 1 ) ) AS L1,
	count( DISTINCT LEFT ( email, 2 ) ) AS L2,
	count( DISTINCT LEFT ( email, 3 ) ) AS L3,
	count( DISTINCT LEFT ( email, 4 ) ) AS L4 
FROM t;
对覆盖索引的影响

使用前缀索引将无法利用覆盖索引机制来优化查询。

即使前缀索引包括了所有的字符串,依然需要回表到主键索引查询,因为系统不确定是否有截断完整的信息

倒序存储和Hash字段

当字符串首部具有足够区分度创建前缀索引,才有可观的收益,例如邮箱等;但如果是身份证字符串,一般前六位是地址码,同一县的人前六位是一样的,这时可能需要很长的前缀才具有足够的区分度。

遇到这种情况,就不适合直接创建前缀索引了,有什么解决方法吗? 一般有两种思路借鉴。

  1. 倒序存储
    • 像身份证这种,前六位可能没什么区分度,但是后六位可是有很高的区分度,如果把它进行倒序存储,倒序的身份证建立前缀索引即可。
    • 每次查询时都要通过 翻转函数reverse处理
  2. 增加 hash 字段
    • 在表上增加一个整数字段,保存身份证的 hash 码,并对这个字段建立索引
    • 每次查询需要通过 hash函数crc32()计算出身份证的 hash 码,作为条件查询。另外,不同身份证可能计算得到的 hash 码一致,这就需要条件加入 身份证精确匹配

两种方法的异同点:

  • 相同点:
    • 两种方式都不支持范围查询。
  • 不同点:
    • 额外占用空间:两者差不多。倒序存储需要建立前缀索引;增加 hash字段是一个整型字段,它的索引长度变为 4个字节,相比前缀索引应该小很多。
    • CPU消耗:倒序存储读写调用 reverse 函数;hash 字段方式需要调用 crc32() 函数。一般来说前者消耗更小。
    • 查询效率:倒序存储还是基于前缀索引;hash 字段更稳定,哈希冲突概率非常小。后者的扫描行数应该会小于前者。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值