❤️ 个人主页:程序员句号
🚀 支持水滴:点赞👍 + 收藏⭐ + 留言💬+关注
🌸 订阅专栏:MySQL性能调优
MySQL性能优化专栏
1.MySQL性能优化1-MySQL底层索引结构
2.MySQL2-Explain详解
3.MySQL3-索引最佳实战
4.MySQL4-MySQL内部组件结构
5.MySQL5-事务隔离级别和锁机制
6.MySQL6-深入理解MVCC和BufferPool缓存机制
索引最佳实战(MySQL优化原则)
示例表:
CREATE TABLE `employees` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(24) NOT NULL DEFAULT '' COMMENT '姓名',
`age` int(11) NOT NULL DEFAULT '0' COMMENT '年龄',
`position` varchar(20) NOT NULL DEFAULT '' COMMENT '职位',
`hire_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '入职时间',
PRIMARY KEY (`id`),
KEY `idx_name_age_position` (`name`,`age`,`position`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COMMENT='员工记录表';
INSERT INTO employees(name,age,position,hire_time) VALUES('LiLei',22,'manager',NOW());
INSERT INTO employees(name,age,position,hire_time) VALUES('HanMeimei', 23,'dev',NOW());
INSERT INTO employees(name,age,position,hire_time) VALUES('Lucy',23,'dev',NOW());
1.全值匹配
EXPLAIN SELECT * FROM employees WHERE name= ‘LiLei’;
EXPLAIN SELECT * FROM employees WHERE name= ‘LiLei’ AND age = 22;
EXPLAIN SELECT * FROM employees WHERE name= ‘LiLei’ AND age = 22 AND position =‘manage
r’;
最左前缀法则
如果索引了多列,要遵守最左前缀法则。指的是查询从索引的最左前列开始并且不跳过索引中的列
EXPLAIN SELECT * FROM employees WHERE name = ‘Bill’ and age = 31; 走
EXPLAIN SELECT * FROM employees WHERE age = 30 AND position = ‘dev’; 不走
EXPLAIN SELECT * FROM employees WHERE position = ‘manager’; 不走
不在索引列上做任何操作
在索引列上做计算、函数、自动or手动类型转换、都会导致索引失效而转向全表扫描
EXPLAIN SELECT * FROM employees WHERE name = ‘LiLei’;
EXPLAIN SELECT * FROM employees WHERE left(name,3) = ‘LiLei’;
给hire_time增加一个普通索引:
ALTER TABLE
employees
ADD INDEXidx_hire_time
(hire_time
) USING BTREE ;
EXPLAIN select * from employees where date(hire_time) =‘2018‐09‐30’;
可以优化成:
这里看到还是没有走索引,这里没走索引的原因并不是因为优化没有起作用,而是因为MySQL的优化器可能认为走索引还没有全表扫描快,因为这里我表的数据很少。但至少possible_keys有值
EXPLAIN select * from employees where hire_time >=‘2018‐09‐30 00:00:00’ and hire_time <
=‘2018‐09‐30 23:59:59’;
还原最初索引状态
ALTER TABLE
employees
DROP INDEXidx_hire_time
;
存储引擎不能使用索引中范围条件右边的列
EXPLAIN SELECT * FROM employees WHERE name= ‘LiLei’ AND age = 22 AND position =‘manager’;
EXPLAIN SELECT * FROM employees WHERE name= ‘LiLei’ AND age > 22 AND position =‘manager’;
为什么范围条件右边的列不会走索引?
因为范围之后,第三个值不一定是有序的,所以只能全表扫描。而为什么不是有序的勒?因为是先按照age来排序的,age相同才会进行排序,我们参考之前的那幅图(图1)就知道了
尽量使用覆盖索引(只访问索引的查询),减少select *语句
EXPLAIN SELECT name,age FROM employees WHERE name= ‘LiLei’ AND age = 23 AND position
=‘manager’;
EXPLAIN SELECT * FROM employees WHERE name= ‘LiLei’ AND age = 23 AND position =‘manager’;