当前位置:网站首页>SQL优化的一些建议,希望可以帮到和我一样被SQL折磨的你
SQL优化的一些建议,希望可以帮到和我一样被SQL折磨的你
2022-08-04 00:05:00 【博学谷狂野架构师】
6.1 优化insert语句
当进行数据的insert操作的时候,可以考虑采用以下几种优化方案。
如果需要同时对一张表插入很多行数据时,应该尽量使用多个值表的insert语句
这种方式将大大的缩减客户端与数据库之间的连接、关闭等消耗。
使得效率比分开执行的单个insert语句快。
示例, 原始方式为:
insert into xxx values(1,'Tom'); insert into xxx values(2,'Cat'); insert into xxx values(3,'Jerry');优化后的方案为 :
insert into xxx values(1,'Tom'),(2,'Cat'),(3,'Jerry');
数据有序插入
insert into tb_test values(4,'Tim'); insert into tb_test values(1,'Tom'); insert into tb_test values(3,'Jerry'); insert into tb_test values(5,'Rose'); insert into tb_test values(2,'Cat');优化后
insert into tb_test values(1,'Tom'); insert into tb_test values(2,'Cat'); insert into tb_test values(3,'Jerry'); insert into tb_test values(4,'Tim'); insert into tb_test values(5,'Rose');
6.2 优化order by语句
6.2.1 环境准备
CREATE TABLE `emp` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`age` int(3) NOT NULL,
`salary` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into `emp` (`id`, `name`, `age`, `salary`) values('1','Tom','25','2300');
insert into `emp` (`id`, `name`, `age`, `salary`) values('2','Jerry','30','3500');
insert into `emp` (`id`, `name`, `age`, `salary`) values('3','Luci','25','2800');
insert into `emp` (`id`, `name`, `age`, `salary`) values('4','Jay','36','3500');
insert into `emp` (`id`, `name`, `age`, `salary`) values('5','Tom2','21','2200');
insert into `emp` (`id`, `name`, `age`, `salary`) values('6','Jerry2','31','3300');
insert into `emp` (`id`, `name`, `age`, `salary`) values('7','Luci2','26','2700');
insert into `emp` (`id`, `name`, `age`, `salary`) values('8','Jay2','33','3500');
insert into `emp` (`id`, `name`, `age`, `salary`) values('9','Tom3','23','2400');
insert into `emp` (`id`, `name`, `age`, `salary`) values('10','Jerry3','32','3100');
insert into `emp` (`id`, `name`, `age`, `salary`) values('11','Luci3','26','2900');
insert into `emp` (`id`, `name`, `age`, `salary`) values('12','Jay3','37','4500');
create index idx_emp_age_salary on emp(age,salary);6.2.2 两种排序方式
1). 第一种是通过对返回数据进行排序,也就是通常说的 filesort 排序
tips
不是通过索引直接返回排序结果的排序都叫 FileSort 排序。
explain select * from emp order by age desc;
explain select * from emp order by age asc;
2). 第二种通过有序索引顺序扫描直接返回有序数据,这种情况即为 using index,
不需要额外排序,操作效率高。
explain select id from emp order by age asc;
explain select id,age from emp order by age asc;
explain select id,age,salary from emp order by age asc;
多字段排序
-- 多字段排序
explain select id,age,salary from emp order by age, salary;
explain select id,age,salary from emp order by age desc, salary desc;
explain select id,age,salary from emp order by salary desc, age desc;
explain select id,age,salary from emp order by age desc, salary asc ;总结:
了解了MySQL的排序方式,优化目标就清晰了:
尽量减少额外的排序,通过索引直接返回有序数据。
where 条件和Order by 使用相同的索引,并且Order By 的顺序和索引顺序相同, 并且Order by 的字段都是升序,或者都是降序。否则肯定需要额外的操作,这样就会出现FileSort。
6.2.3 Filesort 的优化原理
tips
了解即可
通过创建合适的索引,能够减少 Filesort 的出现,但是在某些情况下,条件限制不能让Filesort消失,那就需要加快 Filesort的排序操作。对于Filesort , MySQL 有两种排序算法:
1) 两次扫描算法 :MySQL4.1 之前,使用该方式排序。首先根据条件取出排序字段和行指针信息,然后在排序区 sort buffer 中排序,如果sort buffer不够,则在临时表 temporary table 中存储排序结果。完成排序之后,再根据行指针回表读取记录,该操作可能会导致大量随机I/O操作。
2)一次扫描算法:一次性取出满足条件的所有字段,然后在排序区 sort buffer 中排序后直接输出结果集。排序时内存开销较大,但是排序效率比两次扫描算法要高。
MySQL 通过比较系统变量 max_length_for_sort_data 的大小和Query语句取出的字段总大小, 来判定使用哪种排序算法,如果max_length_for_sort_data 更大,那么使用第二种优化之后的算法;否则使用第一种。
可以适当提高 sort_buffer_size 和 max_length_for_sort_data 系统变量,来增大排序区的大小,提高排序的效率。
show variables like 'max_length_for_sort_data';
show variables like 'sort_buffer_size';6.3 优化group by 语句
tips
延续使用6.2 优化order by语句中创建的表emp
创建索引 (准备工作):
create index idx_emp_age_salary on emp(age,salary); 由于GROUP BY 实际上也同样会进行排序操作,而且与ORDER BY 相比,GROUP BY 主要只是多了排序之后的分组操作。
当然,如果在分组的时候还使用了其他的一些聚合函数,那么还需要一些聚合函数的计算。所以,在GROUP BY 的实现过程中,与 ORDER BY 一样也可以利用到索引。
如果查询包含 group by 但是用户想要避免排序结果的消耗, 则可以执行order by null 禁止排序。如下 :
drop index idx_emp_age_salary on emp;
explain select age,count(*) from emp group by age;
优化后
explain select age,count(*) from emp group by age order by null;
从上面的例子可以看出,第一个SQL语句需要进行"filesort",而第二个SQL由于order by null 不需要进行 "filesort", 而上文提过Filesort往往非常耗费时间。
6.4 优化嵌套查询
tips
延续使用4.3 使用explain分析执行计划中创建的表
Mysql4.1版本之后,开始支持SQL的子查询。这个技术可以使用SELECT语句来创建一个单列的查询结果,然后把这个结果作为过滤条件用在另一个查询中。使用子查询可以一次性的完成很多逻辑上需要多个步骤才能完成的SQL操作,同时也可以避免事务或者表锁死,并且写起来也很容易。但是,有些情况下,子查询是可以被更高效的连接(JOIN)替代。
示例 ,查找有角色的所有的用户信息 :
explain select * from t_user where id in (select user_id from user_role );执行计划为 :

优化后 :
explain select * from t_user u , user_role ur where u.id = ur.user_id;
连接(Join)查询之所以更有效率一些 ,是因为MySQL不需要在内存中创建临时表来完成这个逻辑上需要两个步骤的查询工作。
6.5 使用SQL提示
tips:
延续使用5.2.1 准备环境中创建的表
SQL提示,是优化数据库的一个重要手段,简单来说,就是在SQL语句中加入一些人为的提示来达到优化操作的目的。
6.5.1 USE INDEX
在查询语句中表名的后面,添加 use index 来提供希望MySQL去参考的索引列表,就可以让MySQL不再考虑其他可用的索引。
create index idx_seller_name on tb_seller(name);
explain select * from tb_seller where name='小米科技'
explain select * from tb_seller use index(idx_seller_name) where name='小米科技'
6.5.2 IGNORE INDEX
如果用户只是单纯的想让MySQL忽略一个或者多个索引,则可以使用 ignore index 作为 hint 。
explain select * from tb_seller ignore index(idx_seller_name_sta_addr) where name = '小米科技';
6.5.3 FORCE INDEX
为强制MySQL使用一个特定的索引,可在查询中使用 force index 作为hint 。
create index idx_seller_address on tb_seller(address);
explain select * from tb_seller force index(idx_seller_address) where address = '北京市';
专注Java技术干货分享,欢迎志同道合的小伙伴,一起交流学习
边栏推荐
- 孙宇晨受邀参加36氪元宇宙峰会并发表主题演讲
- 汉字风格迁移---结合本地和全局特征学习的中文字体迁移
- V8中的快慢数组(附源码、图文更易理解)
- [Miscellaneous] How to install the specified font into the computer and then use the font in the Office software?
- 响应式织梦模板除尘器类网站
- Using matlab to solve the linear optimization problem based on matlab dynamic model of learning notes _11 】 【
- libnet
- SRE运维解密-什么是SRE:DevOps模型的具体实践!
- The super perfect layout has shortcut keys and background replacement
- 20年将投资美国约2000亿美元,三星电子财大气粗的样子真好看
猜你喜欢

越来越火的图数据库到底能做什么?

【杂项】如何将指定字体装入电脑然后能在Office软件里使用该字体?

建木DevOps流程的快速运用

Using matlab to solve the linear optimization problem based on matlab dynamic model of learning notes _11 】 【

小身材有大作用——光模块寿命分析(二)

RSS订阅微信公众号初探-feed43

Salesforce's China business may see new changes, rumors may be closing

直播系统聊天技术(八):vivo直播系统中IM消息模块的架构实践

苹果对高通说:我4.45亿美元买下一个新园区,可能计划加快基带芯片自研

Jar a key generation document database
随机推荐
现货白银需要注意八大事项
Free自由协议系统开发
苹果对高通说:我4.45亿美元买下一个新园区,可能计划加快基带芯片自研
RSS feeds WeChat public - feed43 asain
Unity 截取3D图像 与 画中画PIP的实现
响应式织梦模板餐饮酒店类网站
响应式织梦模板除尘器类网站
internship:编写excel表的上传方法(导入)
【MySQL —— 索引】
带你造轮子,自定义一个随意拖拽可吸边的悬浮View组件
【LeetCode】最长回文子序列(动态规划)
Nanoprobes Alexa Fluor 488 FluoroNanogold 偶联物
超级完美版布局有快捷键,有背景置换
The world's first mass production, with the most fixed points!How does this AVP Tier1 lead?
七夕活动浪漫上线,别让网络拖慢和小姐姐的开黑时间
Shell编程之循环语句与函数
全面讲解 Handler机制原理解析 (小白必看)
Apple told Qualcomm: I bought a new campus for $445 million and may plan to speed up self-development of baseband chips
The longest substring that cannot have repeating characters in a leetcode/substring
【杂项】如何将指定字体装入电脑然后能在Office软件里使用该字体?