当前位置:网站首页>SQL调优小记
SQL调优小记
2022-07-06 09:32:00 【Stray_Lambs】
目录
SQL优化
当存在慢SQL时,我们首先需要检测一下SQL语句是否可以进行优化(写SQL的时候就需要思考能否优化),然后,再考虑性能优化。
SQL语句优化
负向查询不能使用索引
当我们使用not in的时候,哪怕中了索引, 也是相当于失效的。
select name from user where id not in (1,3,4);
-- 应该修改为
select name from user where id in (2,5,6);
前导模糊查询不能使用索引
在使用like匹配字符时,若%在前面,则索引失效。
select name from user where name like '%zhangsan'
-- 尽可能改为
select name from user where name like 'zhangsan%'
建议可以考虑使用 Lucene
等全文索引工具来代替频繁的模糊查询。
数据区分不明显时,不应该建立索引
如果数据字段无法明显区分,则不应该建立索引,因为建立索引会消耗空间,就像一本50页的书有50页的目录。
字段的默认值不要为null
null可能会在数据查询时,进行类型的隐式转化,导致索引失效,而且可能会导致查询的结果与预期不一致。
在字段上进行计算不能命中索引
计算函数尽量不要在字段上进行,即不要转换字段类型或者对字段操作(计算、函数、类型转换(手动or自动)),会导致索引失效,转向全表扫描。
select name from user where FROM_UNIXTIME(create_time) < CURDATE();
-- 应该修改为
select name from user where create_time < FROM_UNIXTIME(CURDATE());
最左前缀问题
--如果给 user 表中的 username pwd 字段创建了复合索引那么使用以下SQL 都是可以命中索引:
select username from user where username='zhangsan' and pwd ='axsedf1sd'
select username from user where pwd ='axsedf1sd' and username='zhangsan'
select username from user where username='zhangsan'
-- 但是使用如下,索引无法命中
select username from user where pwd ='axsedf1sd'
明确返回条数
如果明确返回条数,则查询时约束数量,减少查询量,如
select name from user where username='zhangsan' limit 1
不要让数据库自动强制类型转换
如果左右两边类型不一致时,会进行强制类型转换,然后进行全盘扫描。
select name from user where telno=18722222222
--应该修改为
select name from user where telno='18722222222'
join时两表字段类型要相同
不然索引失效,无法命中。
小结
索引失效的产生情况:
1、全值匹配我最爱;
2、最佳左前缀法则;
3、不在索引列上做任何操作(计算、函数、类型转换(手动or自动)),会导致索引失效,转向全表扫描;
4、存储引擎不能使用索引中范围条件右边的列;
5、尽量使用覆盖索引(只访问索引列(查询列和索引列一致)),减少select *;
6、MySQL在使用不等于运算符(!=或<>)时,无法使用索引,会导致全表扫描;
7、is null和is not null,无法使用索引;
8、like若以通配符开头(’%aa’),则索引失效,全表扫描;***–解决方法:1、通配符放左边 2、使用覆盖索引(见P40)***
9、字符串不加引号导致索引失效(相当于使用了隐式的类型转换–见第3条);
10、少用or,用它来连接条件时,索引失效。
口诀
全值匹配我最爱,最左前缀要遵守;
带头大哥不能死,中间兄弟不能断;
索引列上少计算,范围之后全失效;
LIKE百分写最右,覆盖索引不写*;
不等空值还有or,索引失效要少用。
SQL性能优化
使用Explain进行SQL分析
Explain 用来分析 SELECT 查询语句,开发人员可以通过分析 Explain 结果来优化查询语句。
比较重要的字段有:
- select_type : 查询类型,有简单查询、联合查询、子查询等
- key : 使用的索引
- rows : 扫描的行数
优化数据访问量
减少请求的访问量
- 只返回必要的列: 最好不要使用 SELECT * 语句。
- 只返回必要的行: 使用 LIMIT 语句来限制返回的数据。
- 缓存重复查询的数据: 使用缓存可以避免在数据库中进行查询,特别在要查询的数据经常被重复查询时,缓存带来的查询性能提升将会是非常明显的。
减少服务器端扫描行数
最有效的方式是使用索引来覆盖查询。
重构查询方法
切分大查询
一个大查询如果一次性执行的话,可能一次锁住很多数据、占满整个事务日志、耗尽系统资源、阻塞很多小的但重要的查询。每次限定条数,可以有效减少阻塞。
DELEFT FROM messages WHERE create < DATE_SUB(NOW(), INTERVAL 3 MONTH);
-- 应修改为
rows_affected = 0
do {
rows_affected = do_query(
"DELETE FROM messages WHERE create < DATE_SUB(NOW(), INTERVAL 3 MONTH) LIMIT 10000")
} while rows_affected > 0
分解大连接查询
将一个大连接查询分解成对每一个表进行一次单表查询,然后将结果在应用程序中进行关联,这样做的好处有:
- 让缓存更高效。对于连接查询,如果其中一个表发生变化,那么整个查询缓存就无法使用。而分解后的多个查询,即使其中一个表发生变化,对其它表的查询缓存依然可以使用。
- 分解成多个单表查询,这些单表查询的缓存结果更可能被其它查询使用到,从而减少冗余记录的查询。
- 减少锁竞争;
- 在应用层进行连接,可以更容易对数据库进行拆分,从而更容易做到高性能和可伸缩。
- 查询本身效率也可能会有所提升。例如下面的例子中,使用 IN() 代替连接查询,可以让 MySQL 按照 ID 顺序进行查询,这可能比随机的连接要更高效。
SELECT * FROM tab
JOIN tag_post ON tag_post.tag_id=tag.id
JOIN post ON tag_post.post_id=post.id
WHERE tag.tag='mysql';
修改为(有点分布式的思想)
SELECT * FROM tag WHERE tag='mysql';
SELECT * FROM tag_post WHERE tag_id=1234;
SELECT * FROM post WHERE post.id IN (123,456,567,9098,8904);
边栏推荐
- Train 100 pictures for 1 hour, and the style of the photos changes at will. There is a demo at the end of the article | siggraph 2021
- 唯有学C不负众望 TOP1环境配置
- Activit零零碎碎要人命的坑
- TypeScript基本操作
- 唯有学C不负众望 TOP4 S1E6:数据类型
- 原型链继承
- High performance mysql (Third Edition) notes
- yum install xxx报错
- Fdog series (4): use the QT framework to imitate QQ to realize the login interface, interface chapter.
- ~76 sprite map
猜你喜欢
ByteDance open source Gan model compression framework, saving up to 97.8% of computing power - iccv 2021
汇编语言寻址方式
Shell_ 03_ environment variable
搭建flutter环境入坑集合
Fdog series (V): use QT to imitate QQ to realize login interface to main interface, function chapter.
Activiti目录(四)查询代办/已办、审核
~81 long table
Activit fragmented deadly pit
程序员定位解决问题方法论
ByteDance technical Interviewer: what kind of candidate do I want to pick most
随机推荐
~Introduction to form 80
DS18B20數字溫度計系統設計
服务器端渲染(SSR)和客户端渲染(CSR)的区别
How to configure hosts when setting up Eureka
Shell_ 05_ operator
The 116 students spent three days reproducing the ByteDance internal real technology project
Activiti目录(一)重点介绍
8086 segmentation technology
「博士毕业一年,我拿下 ACL Best Paper」
Idea resolving jar package conflicts
唯有學C不負眾望 TOP5 S1E8|S1E9:字符和字符串&&算術運算符
~87 animation
MySQL string function
冯诺依曼体系结构
Only learning C can live up to expectations Top1 environment configuration
Basic knowledge of assembly language
Design of DS18B20 digital thermometer system
Yao BanZhi and his team came together, and the competition experts gathered together. What fairy programming competition is this?
DS18B20数字温度计系统设计
100张图训练1小时,照片风格随意变,文末有Demo试玩|SIGGRAPH 2021