文章目录
2.4. 不能使用索引中范围条件右边的列(范围之后的索引全失效)
2.6. mysql在使用不等于(!=或者<>)的时候无法使用导致全表扫描
2.8. is null和is not null 导致索引失效
+------+-------------+-----------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-----------+------+---------------+------+---------+------+------+-------+
| 1 | SIMPLE | t_blogger | ALL | NULL | NULL | NULL | NULL | 2 | |
+------+-------------+-----------+------+---------------+------+---------+------+------+-------+
MariaDB [db_blog3]> explain select * from t_blog ,t_blogger;
+------+-------------+-----------+------+---------------+------+---------+------+------+------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-----------+------+---------------+------+---------+------+------+------------------------------------+
| 1 | SIMPLE | t_blogger | ALL | NULL | NULL | NULL | NULL | 2 | |
| 1 | SIMPLE | t_blog | ALL | NULL | NULL | NULL | NULL | 16 | Using join buffer (flat, BNL join) |
+------+-------------+-----------+------+---------------+------+---------+------+------+------------------------------------+
t_blogger
,之后查询t_blog
-- 为user表创建组合索引 index_nameAgePos
-- 全值匹配的实例 ,查询的条件的顺序必须和创建索引的顺序一致
select * from t_user where name="Tom" and age=22 and pos="1"
index_nameAgePos
这个索引,实例如下:-- 全值匹配,最为高效
explain select * from t_user where name="Tom" and age=22 and pos="1"
-- 去掉最后一个,使用前两个,那么前两个索引会有效,使用了部分索引
explain select * from t_user where name="Tom" and age=22
-- 去掉后面两个,只是用第一个,索引依然有效,使用了第一个索引的类,部分索引
explain select * from t_user where name="Tom"
-- 去掉第一个,使用后面两个索引查询,没有使用做前缀,索引失效,
explain select * from t_user where and age=22 and pos="1"
-- 去掉中间的一个,只使用第一个和第三个,中间断了,不能查找到索引,索引失效,即使有了做前缀依然会失效
explain select * from t_user where name="Tom" and pos="1"
select * from user where name=2000 ---- 我们知道name是一个varchar类型的,但是用name=2000虽然能够查到,但是在内部其实是将name转换成了数值类型,因此不能使用索引
select * from user where left(name,4)="TOm" -- 这里将对name使用了left这个函数,索引失效
-- age使用了范围查询,那么在其右边的address将不会使用索引查询,但是name和age使用了索引
explain select age from user where name="JOhn" and age>22 and address="江苏";
name,age,address
的组合索引,那么尽量覆盖这三个字段之中的值,mysql将会直接在索引上取值(using index)。并且返回值不包含不是索引的字段name,age,address
select * from user where name="John" or age=22; -- name和age都是索引,生效
select * from user where name="John" or pos=22; -- pos不是索引,因此导致全表扫描,索引失效
%a%
的时候将会导致索引失效explain select * from user where name like "%a%"; -- 索引失效
explain select * from user where name like "a%"; -- 索引生效、
explain select * from user where name like "%a"; --- 索引失效
%$%
查询,那么我们如何解决索引失效?我们可以使用覆盖索引避免索引失效name,age
select * from user where name like "%aa%"; -- 索引失效,没有使用覆盖索引而是select*
select name from user where name like "%a%" ; -- 索引生效,使用了覆盖索引,返回索引列name
select name,age from user where name like "%aa%" -- 索引生效,name和age都是索引
select naem,pos from user where name like "%a" -- 索引失效,pos不是索引
select * from user where pos=2000
,将会导致name这个索引失效,因为mysql在底层会自动为name这个字段进行类型转换-- 没有索引,全表扫描
explain select * from user left join image on user.url=image.url
-- 没有建立索引,全表扫描
select * from t1 left jon t2 t1.name=t2.name left join t3 t2.url=t3.url
t2
的表上为name
字段建立索引,在t3
表上为url
字段建立索引,那么将会使用索引查询left Join
,这种查询是左边的表驱动右边的表,那么我们应该小表驱动大表的策略,对于左连接的时候,左边的表应该是小表,右连接反之name,age,address
select * from user order by name
: 使用索引select * from user order by age
: 不使用索引select * from user order by name,age
: 使用索引,因为排序规则一样并且是左前缀查询select * from user order by name asc,age desc
:不使用索引,因为排序规则不同,即使使用了最佳左前缀where
子句与order by
子句条件列组合满足索引最左前缀查询select * from user where name="John" order by age
: 使用索引,因为where中的name和order by中的age组合在一起符合最佳左前缀原则select * from user where age=22 order by address
:不使用索引sort_buffer_size
的值:不管是使用单路排序还是双路排序,提高这个参数都会提高查询效率max_length_for_sort_data
的值:提高这个参数的值,会增加使用单路排序算法的概率,但是如果设置的太高,数据总容量超出sort_buffer_size的概率增大,明显症状是磁盘I/O活动和低的处理器使用率###