mysql :索引(补充)
EXPLAIN SELECT SQL_NO_CACHE * FROM emp WHERE emp.age=30 and deptid=4 AND emp.name = ‘abcd’;
根据前文所说 创建索引
CREATE INDEX idx_age_deptid_name on emp(age,deptid,name);
1.最左匹配原则
创建索引(a,b,c)相当于创建了 (a) (a,b) (a,b,c)三个索引
如果此时,sql语句换成
EXPLAIN SELECT SQL_NO_CACHE * FROM emp WHERE emp.age=30 AND emp.name = ‘abcd’ ;
或者
EXPLAIN SELECT SQL_NO_CACHE * FROM emp WHERE emp.deptid=1 AND emp.name = ‘abcd’;
之前的索引并不起作用,复合索引 查询从索引的最左前列开始并且不跳过索引中的列。
2.
计算和函数会导致索引失效:
想要使用索引 必须把列单独表示
3.范围右边的列索引失效
4.!= <> 索引失效
5.is not null 无法使用索引。is null 可以
6.like 以% 开头索引失效
7.类型转换导致索引失效
二。关联查询
EXPLAIN SELECT SQL_NO_CACHE * FROM class LEFT JOIN book ON class.card = book.card;
1.采取左连接,索引加在右表上
CREATE INDEX idx_book_card ON book(card);
2.换成inner join(MySQL自动选择驱动表)
inner join 时,mysql会自动将小结果集的表选为驱动表。选择相信mysql优化策略。
三、排序
排序必须包含在索引中,顺序必须与索引中顺序完全相同 或者 反向倒序
EXPLAIN SELECT SQL_NO_CACHE * FROM emp WHERE age =30 AND empno <101000 ORDER BY NAME ;
CREATE INDEX idx_age_empno_name ON emp (age,empno,NAME);
因为empno是一个范围过滤,所以索引后面的字段不会再使用索引了。
此时只能创建一个两个字段的索引。
当【范围条件】和【group by 或者 order by】的字段出现二选一时,优先观察条件字段的过滤数量,如果过滤的数据足够多,而需要排序的数据并不多时,优先把索引放在范围字段上。反之,亦然。
双路排序和单路排序
增大sort_buffer_size参数的设置
增大max_length_for_sort_data参数的设置
减少select 后面的查询的字段。 禁止使用select *
order by 时select * 会让索引失效
group by没有过滤条件,也可以用上索引。Order By 必须有过滤条件才能使用上索引。
覆盖索引:select到from之间的字段使用了索引
尽量使用覆盖索引。不要使用select *