索引分类:
单值索引:一个索引只包含一个列,一个表可以有多个单值索引
唯一索引:索引列的值必须唯一,但允许空值
复合索引:一个索引包含多列
索引语法:
CREATE [UNIQUE] INDEX indexName ON tableName(column1,column2.....) # 创建索引
ALTER tableName ADD [UNIQUE] INDEX [indexName] ON (column1,column2...) # 创建索引
DROP INDEX [indexName] ON tableName # 删除索引
SHOW INDEX FROM tableName # 查看索引
索引结构:
B+树:3层的b+树可以表示上百万数据,所以上百万的数据查找只需要3次IO,性能提高将是巨大的,如果没有索引,每个数据项都要发生一次IO,那么总共需要上百万次IO。
还有Hash等结构,后续不全
哪些字段应该创建索引:
主键(自动创建唯一索引)
频繁作为查询条件的字段
用于关联表的字段
排序字段
查询中统计或分组的字段
覆盖索引:也就是索引覆盖
查询数据时直接从索引中读取数据,不需要读取数据行。也就是查询列被所建的索引覆盖
防止索引失效:
- 最佳左前缀法则,如果索引中包含多列,要遵守最佳左前缀法则,指的是查询从索引的最左前列开始并且不跳过索引中的列
- 不在索引列上做任何操作(计算、函数、类型转换),会导致索引失效
- 范围或like之后索引失效,当使用联合索引时,如果某个索引使用了范围条件,则之后的条件无法使用索引,例:
banji=13 AND age>13 AND name='a'
联合索引包含(banji、age、name),由于age使用了范围条件,导致之后的name条件失效
同理,like之后的字段页会索引失效
- 尽量使用覆盖索引,减少SELECT *。
- 在非唯一索引列使用不等于(!=、<>)会导致索引失效,全表扫描(在唯一索引列使用不等于不会导致全表扫描,执行计划的type是range)
- is null、is not null会导致索引失效
- 字符串不加单引号,索引会失效
- 以通配符开头的like会导致索引失效,例:name like '%fan'
解决方案:如果一定要以通配符开头,使用覆盖索引可以避免全表扫描
案例:只查询主键和city(如果你想查询更多列,应该创建复合索引)
explain select city_id,city from city where city like '%ade%'
其他优化:
小表驱动大表