导语: 马上要过年了, 很多公司也都快放假了, 一年的工作也进入了收尾阶段, 这个时候大家也都进入了准备放假的状态, 但是也不能啥活都不干吧,多对不起公司(工资), 这个时候平时不太注重的东西且非常适合滑水期间做的事情就跳出来了, “压测”, 一个很重要但是又不重要的一个事情啊,. 虽说是划水, 但是也是要拿出点真东西的, 如果你没有, 那我来给你说几个小技巧.
性能优化我们一般会从sql查看执行计划入手, 查看执行计划会从explain工具入手,explain你肯定会用吧,但是具体的列有什么含义, 这列有几个场景,每个场景是什么意思你知道吗?闭上眼睛想想 你真的知道吗?知道, 那你真牛!;不知道?也没关系,我一篇文章给你解释清楚!
关注公众号 程序员小胖 后台回复 "sql优化" 即可获取完整版资料
本片文章主要分享一下在日常工作中经常用到的几个优化小技巧
CREATE TABLE `employees` ( `id` INT ( 16 ) NOT NULL AUTO_INCREMENT, `name` VARCHAR ( 24 ) NOT NULL DEFAULT '' COMMENT '姓名', `age` TINYINT NOT NULL DEFAULT '0' COMMENT '年龄', `position` VARCHAR ( 20 ) NOT NULL DEFAULT '' COMMENT '职位', `create_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY ( `id` ), KEY `idx_name_age_position` (`name`,`age`,`position`) USING BTREE ) ENGINE = INNODB DEFAULT CHARSET = utf8 COMMENT = '记录表';INSERT INTO employees ( name, age, position, create_time )VALUES ('刘备',24,'manager',NOW());INSERT INTO employees ( name, age, position, create_time ) VALUES ('关羽',25,'dev',NOW());INSERT INTO employees ( name, age, position, create_time ) VALUES ('张飞',20,'dev',NOW());
-
全值匹配
EXPLAIN SELECT * FROM employees WHERE name= '刘备';EXPLAIN SELECT * FROM employees WHERE name= '刘备' AND age = 24;EXPLAIN SELECT * FROM employees WHERE name= '刘备' AND age = 24 AND position ='manager'; -
最左索引匹配
EXPLAIN SELECT*FROM employees WHERE name ='刘备' AND age = 24; EXPLAIN SELECT*FROM employees WHERE age = 24 AND position = 'manager'; EXPLAIN SELECT*FROM employees WHERE position = 'manager'; -
不在索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描
EXPLAIN SELECT * FROM employees WHERE name = '刘备';EXPLAIN SELECT * FROM employees WHERE left(name,3) = '刘备';给hire_time增加一个普通索引:
ALTER TABLE `employees` ADD INDEX `create_time_idx` (`create_time`) USING BTREE;EXPLAIN select * from employees where create_time = '2024-01-19 20:54:41';转化为日期查找范围, 有可能会走索引
EXPLAIN select * from employees where create_time > '2024-01-19 20:54:41' and create_time < '2025-01-19 20:54:41' -
存储引擎不能使用索引中范围条件右边的列
EXPLAIN SELECT * FROM employees WHERE name= '刘备' AND age = 24 AND position ='manager';EXPLAIN SELECT * FROM employees WHERE name= '刘备' AND age > 24 AND position ='manager'; -
尽量使用覆盖索引(只访问索引的查询(索引列包含查询列)), 减少 select * 语句
EXPLAIN SELECT name,age FROM employees WHERE name= '刘备' AND age = 24 AND position ='manager';EXPLAIN SELECT * FROM employees WHERE name= '刘备' AND age = 24 AND position ='manager'; -
mysql在使用不等于(!=或者<>),not in, not exists 的时候无法使用索引会导致全表扫描 < 小于、 > 大于、 <=、>= 这些, mysql内部优化器会根据检索比例、表大小等多个因素整体评估是否使用索引.
EXPLAIN SELECT * FROM employees WHERE name != '刘备'; -
is null,is not null 一般情况下也无法使用索引
EXPLAIN SELECT * FROM employees WHERE name is null -
like以通配符开头('$aaa...')mysql索引失效会变成全表扫描操作
EXPLAIN SELECT * FROM employees WHERE name like '%刘'EXPLAIN SELECT * FROM employees WHERE name like '刘%'其实我们平时常用的写法也是有问题的, 不知道你注意到了没有
EXPLAIN SELECT * FROM employees WHERE name like '%刘%'where 条件 name like'%刘%' 一定不会走索引吗?评论区里互动下!
-
字符串不加单引号索引会失效
EXPLAIN SELECT * FROM employees WHERE name = '1000';EXPLAIN SELECT * FROM employees WHERE name = 1000;知道索引为什么会失效吗? 原因是sql执行的时候会强制类型转换, 导致的没走索引
-
少用or或in, 用它查询时, mysql不一定使用索引, mysql内部优化器会根据检索比例、表大小等多个因素整体评 估是否使用索引,详见范围查询优化
EXPLAIN SELECT * FROM employees WHERE name = '刘备' or name = '关羽'; -
范围查询优化
给年龄添加单值索引
ALTER TABLE `employees` ADD INDEX `idx_age` (`age`) USING BTREE;EXPLAIN SELECT * FROM employees WHERE age >=1 and age <=2000;
现在走了索引,原因是因为数据量比较少,所以走了索引
创建一万条数据测试
没走索引原因: mysql内部优化器会根据检索比例、表大小等多个因素整体评估是否使用索引. 比如这个例子,可能是由于单次数据量查询过大导致优化器最终选择不走索引,那对于这种怎么优化呢 可以将大的范围拆分成多个小范围
EXPLAIN EXPLAIN SELECT * FROM employees WHERE age >=1 and age <=1000; EXPLAIN EXPLAIN SELECT * FROM employees WHERE age >=1001 and age <=2000;
看这样是不是一个优化思路呢!