为什么要性能调优
1.提示增删改查速度,提高系统响应速度,能大大优化用户体验感。
2.降低资源的消耗和系统负载,低效的SQL会增加操作系统的各总资源占用,如cpu、内存、网络之类的,在线数据库部在linux,没人会看得下去对远程机器资源大吃特吃,导致不可控风险增加。
3.高效的SQL(时间复杂度小)对软硬件的要求低,通俗的讲,也就是说比较垃圾的硬件服务器上运行高效SQL也能达到在高级的硬件服务器上运行低效SQL的效果,因此SQL性能优化能节约软硬件成本。
性能调优特别重要,数据量小的时候大家觉得无关痛痒,万一是千万级、上亿数据呢?
SQL性能调优的一些原则汇总
1.能合并成为一个语句尽量不要分步为多条SQL,以减少与库的交互次数
假设有两个表:users 和 orders,它们之间存在一对多的关系,一个用户可以有多个订单。现在需要获取用户的信息和对应的订单数量。
常规做法是先查询用户信息,再根据用户的 ID 查询对应的订单数量:
-- 查询用户信息
SELECT * FROM users WHERE id = 1;
-- 查询订单数量
SELECT COUNT(*) FROM orders WHERE user_id = 1;
上述方法需要进行两次查询,分别获取用户信息和订单数量。为了减少查询次数,可以使用连接查询来合并这两个查询:
SELECT u.*, COUNT(o.id) AS order_count
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
WHERE u.id = 1
GROUP BY u.id;
通过连接查询,可以在一次查询中获取用户信息和对应的订单数量。这样就减少了一次与数据库的交互次数,提高了查询的效率。
2.尽量保证条件查询where后面的字段是有索引的字段,这样能大大加快
假设student表有几千万条数据:
select * from student where name = 'LiMing'
select * from student where stu_id = '1904080156'
上述中查询同一个学生,如果学号stu_id设置索引,那么后者速度会快得多;
同时,使用索引也不会像上述使用name查询一样全表扫描,这样就提示了效率。
3.尽量进行干净的查询,不需要查的字段就不要带了
select * from student
select stu_id,name from student
如果只需要查询学生表中的学号和姓名,那就万万不能select *了,这样低效,不必要的不要查。
不过这样提示性能的效果相对于索引提升不是那么明显。
4.嵌套查询(有子查询)的优化原则
※ 使用连接查询代替子查询
select name from student
where stu_id in (select stu_id from dept_computer);
select s.name from student s,dept_computer d where s.stu_id=d.stu_id;
上述如果要查计算机系的学生姓名,使用后者连接查询的性能相对好些。
※ 对于IN关键字后面的子程序,尽量用exists代替,也能提升性能:
select name from student
where stu_id in (select stu_id from dept_computer);
select name from student s
where exists (select * from dept_computer d where s.stu_id = d.stu_id);
※ 减少嵌套的层数
原则上,如果嵌套能化解成连接查询就尽量化成连接查询。
5.如果数据库(如oracle中)有多个实例尽量少使用DBlink
dblink是在指定数据库实例中获取其他实例的表,这种方式产生的查询时间要比直接在该实例中执行查询的时间要长:
select * from student@db_instance1
其他一些解决SQL低效问题的办法(非调优)
1…最后还可以通过缓存的方式来解决SQL性能(如redis,这个大家可以去专攻自学下)
还有一些方式如使用Oracle自带的高速缓存数据库TT等方式…
这个方式很强大,但是内容上就不属于sql调优了,它只是把第一次sql语句的执行结果放到缓存中,下次执行的sql只需要在缓存获取数据,从而大大加快sql执行速度。
2.当然,网络的好坏对SQL执行的速度也是正相关的影响的
这是因为sql请求会在网络上进行传输,网络性能直接影响SQL执行速度,所以为什么要避免查询不必要的列?就是避免不必要的数据量造成网络传输量大,因此减少列以减少网络性能对查询效率的影响。这也不是SQL调优的范畴了,而是其他一些因素…
3.分布式、分片/分区思想
试想一下,一个表数据量特别多,那全表扫描不管sql如何调优,查询的时间复杂度很可能还是很大;所以有个类似于数据结构中分块查找的思想,设置分区表把,实现把数据进行分区,如果定位需要查找的记录在特定的分区,而每个分区的数据量相对于全表来说就比较少了,这样就能明显加快速度,当然 我只是了解一下这种思路,大家可以进行这方面具体深入的学习…