8.索引相关
8.0 联合索引和最左匹配原则
最左匹配原则:以最左边的起点任何连续的索引都能匹配上。同时遇到范围查询(>、<、between、like、in)就会停止匹配。
联合索引:combine_index(a, b, c); 根据最左匹配规则,用到索引的子集为以下两种情况:
情况一:第一列匹配,后面可以缺失n列
a
a, b
a, c(只用到了索引a,效果等同于a)
情况二:完全匹配所有列
a, b, c
以上的匹配都是指精确匹配.
a.前缀匹配:...where nike like 'asd%'。
前缀匹配可使用索引,中缀和后缀匹配就只能全盘扫描了。
b.范围匹配:...where a > 1 and a < 5 and b > 1;
多个列同时进行范围匹配查找时,只针对最左边的那个列进行范围查找时用到了索引(B+树)
c.精确匹配某一列并范围匹配另外一列
select * from table_name where a = 1 and b > 3;
如果左边的列是精确查找,右边的列可以进行范围查找
d.索引列使用函数后,索引当即失效
比如常用日期相关函数:date()、datediff(date1,date2)、date_format(timestamp1,'%Y-%m-%d')等
log_time为索引,查看某一天的玩家日志,以下5种方式中,只有2和3用到了索引
1.explain select * from `player_log` where DATEDIFF(date(`log_time`),CURDATE()) = -1;
2.explain select * from `player_log` where `log_time` BETWEEN '2020-11-04 00:00:00' AND '2020-11-05 00:00:00';
3.explain select * from `player_log` where `log_time` >= '2020-11-04 00:00:00' and `log_time` < '2020-11-05 00:00:00';
4.explain select * from `player_log` where DATE_FORMAT(log_time,'%Y-%m-%d') = '2020-11-04';
5.explain select * from `player_log` where date(log_time) = '2020-11-04';
优化方式:使用范围查询取代函数
8.2 多列索引(覆盖索引)
什么是覆盖索引?
满足查询中给定表用到的所有列,包括where语句、order by语句、group by语句、以及select语句中的所有列
ex: select a, b from table123 where c = 110 order by d desc; (index_all(c, d, a, b))
注意:mysql通常一次查询只能使用一个索引,这是由B+树的结构决定的。而不是我们自以为的建两条单列的索引就能起到叠加的效果
#step1.假设artist_id是主键,没有创建索引
select artist_id, type, name from artist where type = 'Person';
#step2.创建单列索引后,以上select语句速度显著提高。
alter table artist add key index_type(type);
#step3.创建多列索引(覆盖索引)后,以上select语句速度进一步提高。
alter table artist add key index_type_name(type, name);
说明:为何artist_id没有包括在覆盖索引内?
innodb非主码索引特性:在innodb中,主码的值会被附加在非主码索引的每个对应记录后面,因此没有必要在非主码索引中指定主码。
即,innodb引擎中所有非主码索引都隐含主码列了。
#step4.添加多个索引,合并DML语句,提高效率(创建索引语句,非常耗时,并且会阻塞其他操作)
alter table artist add index index_type(type), add index index_type_name(type, name);
#分开成两条alter语句,在生产环境消耗的时间较多
#创建index_type和index_type_name两个索引显然重复了,此处仅为了举例说明
8.3索引覆盖where和order by语句
建立一个同时满足 where语句 和 order by语句 的索引
8.3 查看索引语句
show index from table_abc;
查看表当前创建的索引
8.4 生产环境中创建索引考虑的因素
a.alter是DDL语句,执行时会阻塞所有DML(查询/修改/添加)语句。
b.如果表数据比较大,alter语句执行时间会比较长。
c.一个表有多个索引情况下DML的性能开销。
添加索引前至少做两项检查:
a.验证表的现有结构 b.确定表的大小
8.5 索引提高表连接查找效率
在表连接的列上使用索引,可以显著提升性能
8.6 不要再select查询中使用:select *
因为如果在select语句中只包含那些真正需要的列,就能顺利通过创建合适的索引来获得更好的SQL优化。