一次SQL优化经历

简介:

最近遇到一个SQL执行很慢。这个SQL比较长,但基本的形态比较简单:

SELECT T1.*, T2.C1 .... FROM T1 LEFT JOIN T2 ON T1.C1 = T2.C1 LEFT JOIN T3 ON T1.C2 = T3.C1 LEFT JOIN T3 ON T1.C3 = T3.C1 ....

  1. 执行explain ,直接查看执行计划。发现很多的SeqScan(表扫描)。其中有一个表T3,被反复连接,且每次连接都使用了表扫描:

screenshot

先看看这张表的情况,实际上连接使用的都是C1字段,而这个字段上有索引,为什么没有使用?利用select count(*) from T3,看到此张表的数据量不大(13393),这可能是优化器为选择索引的原因(数据量过小),但也可能是 统计信息不准确造成,执行了ANALYZE T3未见变化。(后来发现是这样,当加入LIMIT子句,且limit小于10000时,使用的是索引扫描,否则使用的是表扫描,这是由优化器根据代价评估决定的,并没有问题。)

这里,我们感觉执行计划基本没有问题。

  1. 用explain analyze 分析SQL执行过程中,哪个环节耗费了最多时间。直接执行发现长时间得不到结果,所以加入了LIMIT子句,即 explain analyze limit 1000,执行耗时8秒多。查询计划中处理了对T4等表的表扫描,但这些表数据量都不大。仔细查看查询计划中的actual time的变化情况,发现在第二行出现了一个不正常的现象:actual time=11.614..8913.433 。这个数据中,11.614代表输出第一行时所用的时间,8913.433 代码输出所有行的时间,也就是说输出第一行用了11ms,输出1000行用了8.9秒!

screenshot

查看最后一行,发现了原因,这里有个SubPlan,就是每次输出一行前都要计算一下这个SubPlan,而这个Subplan含有对T1的一次表扫描,就是说每次都要对hr_users全部扫描一次,返回1000条结果要扫描1000次T1。hr_users有2万多条记录,即总计扫描2000万左右的记录!

screenshot

  1. 查看SQL,发现这个Subplan对应一个SELECT里面的子查询,里面有个条件是WHERE TO_CHAR(T1.C10) = TO_CHAR(TEMP.C20)) ,而我们知道这种TO_CHAR转换容易造成索引无法使用(USER_ID是数字类型)。将这个条件改为:T1.C10 = TO_number(TEMP.C20)) (还需要业务评估是否可以这样改!),上述语句的运行时间由8秒降低至100多ms!!
  2. 试着执行explain analyze limit 30000,发现与T2的连接的计划中含有如下提示:
    screenshot

即与T2的连接过滤了很多记录,怀疑是否这个连接是性能瓶颈。而T2是个View,于是试着把这个View的结果插入到一个表中,并建立索引,使用这个表替换T2,发现作用不大。

  1. 为了防止统计信息不准确,运行了如下的语句收集查询中涉及的表的统计信息:

  2. T1;
  3. T2;
    Analyze T3;
    Analyze T4;

上述修改后,大幅降低了原SQL的查询延迟。直接执行这个SQL结果超过数十万行,因此进一步的优化,需要查看这个SQL是如何使用的,根据场景进行优化。

目录
相关文章
|
16天前
|
SQL 存储 关系型数据库
如何巧用索引优化SQL语句性能?
本文从索引角度探讨了如何优化MySQL中的SQL语句性能。首先介绍了如何通过查看执行时间和执行计划定位慢SQL,并详细解析了EXPLAIN命令的各个字段含义。接着讲解了索引优化的关键点,包括聚簇索引、索引覆盖、联合索引及最左前缀原则等。最后,通过具体示例展示了索引如何提升查询速度,并提供了三层B+树的存储容量计算方法。通过这些技巧,可以帮助开发者有效提升数据库查询效率。
34 2
|
2天前
|
SQL 资源调度 分布式计算
如何让SQL跑快一点?(优化指南)
这篇文章主要探讨了如何在阿里云MaxCompute(原ODPS)平台上对SQL任务进行优化,特别是针对大数据处理和分析场景下的性能优化。
|
11天前
|
SQL 监控 数据库
慢SQL对数据库写入性能的影响及优化技巧
在数据库管理系统中,慢SQL(即执行缓慢的SQL语句)不仅会影响查询性能,还可能对数据库的写入性能产生显著的不利影响
|
14天前
|
SQL 关系型数据库 PostgreSQL
遇到SQL 子查询性能很差?其实可以这样优化
遇到SQL 子查询性能很差?其实可以这样优化
51 2
|
11天前
|
SQL 存储 数据库
慢SQL对数据库写入性能的影响及优化技巧
在数据库管理系统中,慢SQL(即执行缓慢的SQL语句)不仅会影响查询性能,还可能对数据库的写入性能产生显著的不利影响
|
14天前
|
SQL 数据处理 数据库
SQL语句优化与查询结果优化:提升数据库性能的实战技巧
在数据库管理和应用中,SQL语句的编写和查询结果的优化是提升数据库性能的关键环节
|
14天前
|
SQL 存储 数据库
慢SQL对数据库写入性能的影响及优化策略
在数据库管理系统中,慢SQL(即执行缓慢的SQL语句)不仅会影响查询性能,还可能对数据库的写入性能产生不利影响
|
2月前
|
SQL
慢sql治理问题之 Task 数量分布不均的问题你们是如何优化的
慢sql治理问题之 Task 数量分布不均的问题你们是如何优化的
慢sql治理问题之 Task 数量分布不均的问题你们是如何优化的
|
2月前
|
Java XML Maven
跨越时代的飞跃:Struts 2 升级秘籍——从旧版本无缝迁移到最新版,焕发应用新生!
【8月更文挑战第31天】随着软件技术的发展,Struts 2 框架也在不断更新。本文通过具体案例指导开发者如何从旧版平滑升级到 Struts 2.6.x。首先更新 `pom.xml` 中的依赖版本,并执行 `mvn clean install`。接着检查 `struts.xml` 配置,确保符合新版本要求,调整包扫描器等设置。审查 Action 类及其注解,检查配置文件中的弃用项及插件。更新自定义拦截器实现,并验证日志配置。最后,通过一系列测试确保升级后的系统正常运行。通过这些步骤,可以顺利完成 Struts 2 的版本升级,提升应用的安全性和性能。
142 0
|
2月前
|
SQL 存储 数据库