高性能的索引使用策略
1.不在索引列上做任何操作
我们通常会看到一些查询不当地使用索引,或者使得MySQL无法使用已有的索引。如果查询中的列不是独立的,则 MySQL就不会使用索引。“独立的列”是指索引列不能是表达式的一部分,也不能是函数的参数。
例如,我们假设id上有主键索引,但是下面这个查询无法使用主键索引:
EXPLAIN SELECT * FROM order_exp WHERE id + 1 = 17;
凭肉眼很容易看出 WHERE中的表达式其实等价于id= 16,但是MySQL无法自动解析这个方程式。这完全是用户行为。我们应该养成简化WHERE条件的习惯,始终将索引列单独放在比较符号的一侧。
下面是另一个常见的错误:
在索引列上使用函数,也是无法利用索引的。
EXPLAIN SELECT * from order_exp WHERE YEAR(insert_time)=YEAR(DATE_SUB(NOW(),INTERVAL 1 YEAR));
EXPLAIN SELECT * from order_exp WHERE insert_time BETWEEN str_to_date('01/01/2021', '%m/%d/%Y') and str_to_date('12/31/2021', '%m/%d/%Y');
2.尽量全值匹配
建立了联合索引列后,如果我们的搜索条件中的列和索引列一致的话,这种情况就称为全值匹配,比方说下边这个查找语句:
EXPLAIN select * from order_exp where insert_time='2021-03-22 18:34:55' and order_status=0 and expire_time='2021-03-22 18:35:14';
我们建立的u_idx_day_statusr索引包含的3个列在这个查询语句中都展现出来了,联合索引中的三个列都可能被用到。
有的同学也许有个疑问,WHERE子句中的几个搜索条件的顺序对查询结果有啥影响么?也就是说如果我们调换 insert_time
, order_status
, expire_time
这几个搜索列的顺序对查询的执行过程有影响么?比方说写成下边这样:
EXPLAIN select * from order_exp where order_status=0 and insert_time='2021-03-22 18:34:55' and expire_time='2021-03-22 18:35:14';
放心,MySQL没这么蠢,查询优化器会分析这些搜索条件并且按照可以使用的索引中列的顺序来决定先使用哪个搜索条件,后使用哪个搜索条件。
所以,当建立了联合索引列后,能在where条件中使用索引的尽量使用。
3.最佳左前缀法则
建立了联合索引列,如果搜索条件不够全值匹配怎么办?在我们的搜索语句中也可以不用包含全部联合索引中的列,但要遵守最左前缀法则。指的是查询从索引的最左前列开始并且不跳过索引中的列。
搜索条件中必须出现左边的列才可以使用到这个B+树索引
EXPLAIN select * from order_exp where insert_time='2021-03-22 18:23:42' and order_status=1;
EXPLAIN select * from order_exp where insert_time='2021-03-22 18:23:42' ;
搜索条件中没有出现左边的列不可以使用到这个B+树索引
EXPLAIN SELECT * FROM order_exp WHERE order_status=1;
EXPLAIN Select * from s1 where order_status=1 and expire_time='2021-03-22 18:35:14';
那为什么搜索条件中必须出现左边的列才可以使用到这个B+树索引呢?比如下边的语句就用不到这个B+树索引么?
因为