一、长字段索引优化
1、额外创建一个hash字段,作为索引(B+tree的伪hash)
hash算法应满足(一般使用crc32或fnv64): a、字段长度应该比较小(SHA1/MD5不合适) b、尽量避免hash冲突 示例:select * from t_goods where name = 'windge-name很长' 优化:select * from t_goods where name_hash = CRC32('windge-name很长') and name = 'windge-name很长'2、使用前缀索引
示例:select * from t_goods where name like 'windge-name%' 优化:select * from t_goods where name_hash = CRC32('windge-name很长') and name = 'windge-name很长' ALTER TABLE `t_goods` ADD INDEX idx_name ( name(5) ) 前缀索引的长度如何设定: 索引选择性 = 不重复的索引值/数据表的总记录数 数值越大,性能越好 最大选择性:select count(distinc name) / count(*) from t_goods 测试接近最大选择性的长度:select count(distinc left(name,7)) / count(*) from t_goods 局限性:无法做order by、group by,无法使用覆盖索引3、后缀索引
将数据翻转保存,再添加一个前缀索引。 示例:select * from t_goods where name like '%windge-name' 优化:select * from t_goods where name_reverse like 'eman-egdinw%'二、单例索引和组合索引
示例:index(create_time)和index(pay_time)两个单例索引时:select * from t_order WHERE create_time >= '2020-01-01' AND pay_time>= '2020-02-03'; 优化:添加或者修改为组合索引,因为组合索引的性能高于多个单例的索引 分析: SQL存在多个条件,多个单列索引,会使用索引合并,单列索引会产生一个求交集的开销,这会导致单列索引的性能稍微低于组合索引(可以在OPTIMIZER TRACE中求出来); SET OPTIMIZER_TRACE="enabled=on",END_MARKERS_IN_JSON=ON; SET optimizer_trace_offset=-30, optimizer_trace_limit=30; SELECT * from information_schema.OPTIMIZER_TRACE ot WHERE ot.QUERY LIKE '%t_order%'; 说明:如果出现索引合并,说明索引不够合理,但是如果SQL暂时没有性能问题,暂时可以不管,避免过度优化三、覆盖索引
定义:select字段的数据直接从索引中就可以拿到,不用再去数据节点获取数据,这样叫做覆盖索引(索引已覆盖了要取的字段内容,优点显然就是不用再去数据节点取数据) 示例:select create_time,pay_time from t_order WHERE create_time = '2020-01-01' and pay_time= '2020-02-01'; 优化条件:带索引alter TABLE t_order add index idx_create_time_pay_time(create_time,pay_time); 标志:explain分析结果的Extra 显示 Using index,OPTIMIZER TRACE中显示 best_covering_index_scan中choose为true 启发:要利用覆盖索引提升性能就要尽可能的按需返回查询字段四、避免冗余索引
定义:如果已经存在索引index(A, B) , 又创建了index(A) , 那么index(A)就是index(A, B)的冗余索引 一般冗余索引都要删除,但是也有例外 例外的示例: select * from t_order WHERE create_time = '2020-01-01' order by id ; 单例索引时分析
组合索引时分析
Using filesort说明排序未能使用索引 例外原因说明:
- 当使用了组合索引index idx_create_time_pay_time(create_time,pay_time)后,id的索引失效
- 因为id是主键,使用了主键索引
- 当使用组合索引的时候,相当于 index(create_time,pay_time,id)
- 根据最左前缀原则,id的索引会失效;