MySQL优化器的索引选择与字符串索引
优化器的逻辑
- 扫描行数的多少
- 是否使用临时表
- 是否排序
扫描行数怎么判断
MySQL在开始统计之前并不能精确的知道满足这个条件的记录有多少条,只能根据**索引的“区分度”**来估算记录数
MySQL通过采样统计一个索引上的不同值的个数来统计区分度,不同值的个数越多,索引的区分度越好
索引选择异常处理
- 对于由于索引统计信息不准确导致的问题 analyze table t 命令,可以用来重新统计索引信息
- 对于其他优化器误判的问题:
- force index 强行选择一个索引
缺点:如果索引改了名字,这个语句也得改,显得很麻烦。而且如果以后迁移到别的数据库的话,这个语法还可能会不兼容 - 修改语句,引导 MySQL 使用我们期望的索引
- 如果索引改了名字,这个语句也得改,显得很麻烦。而且如果以后迁移到别的数据库的话,这个语法还可能会不兼容
为长字符串加索引
- 使用前缀索引
优点:节省空间
缺点:1. 会增加额外的记录扫描次数 2. 不能使用覆盖索引对查询性能进行优化 - 使用倒序存储,再创建前缀索引,用于绕过字符串本身前缀的区分度不够的问题
比如:在查询身份证号时,将身份证号倒过来存储
mysql> select field_list from t where id_card = reverse('input_id_card_string');
- 使用 hash 字段。你可以在表上再创建一个整数字段,来保存身份证的校验码,同时在这个字段上创建索引。
使用hash索引和倒序异同
- 从占用的额外空间来看,倒序存储方式在主键索引上,不会消耗额外的存储空间,而hash 字段方法需要增加一个字段。当然,倒序存储方式使用 4 个字节的前缀长度应该是不够的,如果再长一点,这个消耗跟额外这个 hash 字段也差不多抵消了。
- 在 CPU 消耗方面,倒序方式每次写和读的时候,都需要额外调用一次 reverse 函数,而hash 字段的方式需要额外调用一次 crc32() 函数。如果只从这两个函数的计算复杂度来看的话,reverse 函数额外消耗的 CPU 资源会更小些。
- 从查询效率上看,使用 hash 字段方式的查询性能相对更稳定一些。因为 crc32 算出来的值虽然有冲突的概率,但是概率非常小,可以认为每次查询的平均扫描行数接近 1。而倒序存储方式毕竟还是用的前缀索引的方式,也就是说还是会增加扫描行数。