通过调整表union all的顺序优化SQL

简介: 原文:通过调整表union all的顺序优化SQL  操作系统:Windows XP   数据库版本:SQL Server 2005   今天遇到一个SQL,过滤条件是自动生成的,因此,没法通过调整SQL的谓词达到优化的目的,只能去找SQL中的“大表”。
原文: 通过调整表union all的顺序优化SQL

  操作系统:Windows XP

  数据库版本:SQL Server 2005

  今天遇到一个SQL,过滤条件是自动生成的,因此,没法通过调整SQL的谓词达到优化的目的,只能去找SQL中的“大表”。有一个视图返回的结果集比较大,如果能调整的话,也只能调整该视图了。

  看了一下该视图的结构,里面还套用了另一层视图,直接看最里层视图的查询SQL。

SELECT  a.dfeesum_no ,
        a.opr_amt - ISNULL(b.dec_pay, 0) - ISNULL(b.dec_corrpay, 0)
        - ISNULL(b.dec_deduamt, 0) dec_amt ,
        a.dec_camt - ISNULL(b.dec_pay, 0) - a.dec_comprate
        * ISNULL(b.dec_deduamt, 0) dec_compamt ,
        a.dec_ramt - ISNULL(b.dec_corrpay, 0) - ( a.dec_comprate - 1 )
        * ISNULL(b.dec_deduamt, 0) dec_corramt ,
        a.dec_qty - ISNULL(b.dec_qty, 0) - ISNULL(b.dec_deduqty, 0) opr_qty ,
        ISNULL(b.dec_pay, 0) dec_pay ,
        ISNULL(b.dec_corrpay, 0) dec_corrpay ,
        ISNULL(b.dec_deduqty, 0) dec_deduqty ,
        ISNULL(b.dec_deduamt, 0) dec_deduamt ,
        ISNULL(b.dec_qty, 0) dec_qty
FROM    ctlm8686 a
        LEFT JOIN ( SELECT  dfeesum_no ,
                            SUM(dec_ramt) dec_pay ,
                            SUM(dec_corramt) dec_corrpay ,
                            SUM(dec_qty) dec_qty ,
                            SUM(CASE WHEN flag_dedu = '1' THEN dec_deduamt
                                     ELSE 0
                                END) dec_deduamt ,
                            SUM(CASE WHEN flag_dedu = '1' THEN dec_deduqty
                                     ELSE 0
                                END) dec_deduqty
                    FROM    dfeepay_03
                    GROUP BY dfeesum_no
                  ) b ON a.dfeesum_no = b.dfeesum_no
UNION ALL
SELECT  a.dfeesum_no ,
        a.dec_amt - ISNULL(b.dec_pay, 0) - ISNULL(b.dec_corrpay, 0)
        - ISNULL(b.dec_deduamt, 0) dec_amt ,
        a.dec_compamt - ISNULL(b.dec_pay, 0) - a.dec_comprate
        * ISNULL(b.dec_deduamt, 0) dec_compamt ,
        a.dec_corramt - ISNULL(b.dec_corrpay, 0) - ( a.dec_comprate - 1 )
        * ISNULL(b.dec_deduamt, 0) dec_corramt ,
        a.opr_qty - ISNULL(b.dec_qty, 0) - ISNULL(b.dec_deduqty, 0) opr_qty ,
        ISNULL(b.dec_pay, 0) dec_pay ,
        ISNULL(b.dec_corrpay, 0) dec_corrpay ,
        ISNULL(b.dec_deduqty, 0) dec_deduqty ,
        ISNULL(b.dec_deduamt, 0) dec_deduamt ,
        ISNULL(b.dec_qty, 0) dec_qty
FROM    dfeeapp_03 a
        LEFT JOIN ( SELECT  dfeesum_no ,
                            SUM(dec_ramt) dec_pay ,
                            SUM(dec_corramt) dec_corrpay ,
                            SUM(dec_qty) dec_qty ,
                            SUM(CASE WHEN flag_dedu = '1' THEN dec_deduamt
                                     ELSE 0
                                END) dec_deduamt ,
                            SUM(CASE WHEN flag_dedu = '1' THEN dec_deduqty
                                     ELSE 0
                                END) dec_deduqty
                    FROM    dfeepay_03
                    GROUP BY dfeesum_no
                  ) b ON a.dfeesum_no = b.dfeesum_no

  返回结果集有1433891行,其中

  SELECT COUNT(*) FROM dfeepay_03 --1103914
  SELECT COUNT(*) FROM ctlm8686 --1131586
  SELECT COUNT(*) FROM dfeeapp_03--302305

  上述SQL脚本中,子查询是相同的,即对子查询进行了两次扫描,可以考虑先让dfeeapp_03和ctlm8686union all,再left join dfeepay_03 。同时,对于子查询,先让dfeepay_03 表先查询出flag_dedu = '1'的数据,就不用再进行case when判断了。

  改写后的SQL如下

SELECT  a.dfeesum_no ,
        a.opr_amt - ISNULL(b.dec_pay, 0) - ISNULL(b.dec_corrpay, 0)
        - ISNULL(b.dec_deduamt, 0) dec_amt ,
        a.dec_camt - ISNULL(b.dec_pay, 0) - a.dec_comprate
        * ISNULL(b.dec_deduamt, 0) dec_compamt ,
        a.dec_ramt - ISNULL(b.dec_corrpay, 0) - ( a.dec_comprate - 1 )
        * ISNULL(b.dec_deduamt, 0) dec_corramt ,
        a.dec_qty - ISNULL(b.dec_qty, 0) - ISNULL(b.dec_deduqty, 0) opr_qty ,
        ISNULL(b.dec_pay, 0) dec_pay ,
        ISNULL(b.dec_corrpay, 0) dec_corrpay ,
        ISNULL(b.dec_deduqty, 0) dec_deduqty ,
        ISNULL(b.dec_deduamt, 0) dec_deduamt ,
        ISNULL(b.dec_qty, 0) dec_qty
FROM    ( SELECT    a.dfeesum_no ,
                    a.opr_amt ,
                    a.dec_camt ,
                    a.dec_comprate ,
                    a.dec_ramt ,
                    a.dec_qty
          FROM      ctlm8686 a
          UNION ALL
          SELECT    a.dfeesum_no ,
                    a.dec_amt ,
                    a.dec_compamt ,
                    a.dec_comprate ,
                    a.dec_corramt ,
                    a.opr_qty
          FROM      dfeeapp_03 a
        ) a
        LEFT JOIN ( SELECT  dfeesum_no ,
                            SUM(dec_ramt) dec_pay ,
                            SUM(dec_corramt) dec_corrpay ,
                            SUM(dec_qty) dec_qty ,
                            SUM(dec_deduamt) dec_deduamt,
                            SUM(dec_deduqty) dec_deduqty
                    FROM   dfeepay_03
                    WHERE flag_dedu = '1'
                    GROUP BY dfeesum_no
                  ) b ON a.dfeesum_no = b.dfeesum_no                

  跑这个视图的查询语句,从原来的一分半钟降到一分钟,对于整个SQL而言,则从原来跑几分钟的直接10S出结果。

 

目录
相关文章
|
SQL 关系型数据库 MySQL
MySQL进阶突击系列(07) 她气鼓鼓递来一条SQL | 怎么看执行计划、SQL怎么优化?
在日常研发工作当中,系统性能优化,从大的方面来看主要涉及基础平台优化、业务系统性能优化、数据库优化。面对数据库优化,除了DBA在集群性能、服务器调优需要投入精力,我们研发需要负责业务SQL执行优化。当业务数据量达到一定规模后,SQL执行效率可能就会出现瓶颈,影响系统业务响应。掌握如何判断SQL执行慢、以及如何分析SQL执行计划、优化SQL的技能,在工作中解决SQL性能问题显得非常关键。
|
11月前
|
SQL 存储 监控
SQL日志优化策略:提升数据库日志记录效率
通过以上方法结合起来运行调整方案, 可以显著地提升SQL环境下面向各种搜索引擎服务平台所需要满足标准条件下之数据库登记作业流程综合表现; 同时还能确保系统稳健运行并满越用户体验预期目标.
485 6
|
SQL 存储 自然语言处理
SQL的解析和优化的原理:一条sql 执行过程是什么?
SQL的解析和优化的原理:一条sql 执行过程是什么?
SQL的解析和优化的原理:一条sql 执行过程是什么?
|
SQL 数据格式
SQL 无法使用Union如何解决
SQL Server中使用UNION时,若字段含ntext类型会报错。可通过查询INFORMATION_SCHEMA.COLUMNS定位该字段,并用CAST转为nvarchar即可解决。
|
SQL 关系型数据库 MySQL
如何优化SQL查询以提高数据库性能?
这篇文章以生动的比喻介绍了优化SQL查询的重要性及方法。它首先将未优化的SQL查询比作在自助餐厅贪多嚼不烂的行为,强调了只获取必要数据的必要性。接着,文章详细讲解了四种优化策略:**精简选择**(避免使用`SELECT *`)、**专业筛选**(利用`WHERE`缩小范围)、**高效联接**(索引和限制数据量)以及**使用索引**(加速搜索)。此外,还探讨了如何避免N+1查询问题、使用分页限制结果、理解执行计划以及定期维护数据库健康。通过这些技巧,可以显著提升数据库性能,让查询更高效流畅。
|
SQL 开发框架 .NET
【YashanDB知识库】使用c-调用yashandb odbc驱动执行SQL时报YAS-08008 not all variables bounded
本文来自YashanDB官网,讨论了某客户在使用C# ASP.NET应用时遇到的异常问题。问题表现为YashanDB ODBC驱动不支持.NET框架通过绑定变量执行SQL语句,导致应用无法正常运行。该问题影响所有YashanDB版本及其ODBC驱动版本。解决方法包括避免使用绑定变量或升级ODBC驱动版本。文章通过示例代码展示了问题复现过程,并总结了最小化问题场景以定位和解决问题的经验。
|
SQL 关系型数据库 MySQL
基于SQL Server / MySQL进行百万条数据过滤优化方案
对百万级别数据进行高效过滤查询,需要综合使用索引、查询优化、表分区、统计信息和视图等技术手段。通过合理的数据库设计和查询优化,可以显著提升查询性能,确保系统的高效稳定运行。
971 9
|
SQL 开发框架 .NET
【YashanDB 知识库】使用 c- 调用 yashandb odbc 驱动执行 SQL 时报 YAS-08008 not all variables bounded
某客户C# ASP.NET应用在使用yashandb ODBC驱动时,因驱动不支持绑定变量执行SQL语句而报错“YAS-08008 not all variables bounded”,导致应用无法正常运行。影响所有yashandb及ODBC驱动版本。解决方法为避免使用绑定变量或升级驱动版本。通过简化场景成功复现问题。
|
SQL Oracle 关系型数据库
如何在 Oracle 中配置和使用 SQL Profiles 来优化查询性能?
在 Oracle 数据库中,SQL Profiles 是优化查询性能的工具,通过提供额外统计信息帮助生成更有效的执行计划。配置和使用步骤包括:1. 启用自动 SQL 调优;2. 手动创建 SQL Profile,涉及收集、执行调优任务、查看报告及应用建议;3. 验证效果;4. 使用 `DBA_SQL_PROFILES` 视图管理 Profile。
|
SQL Oracle 数据库
使用访问指导(SQL Access Advisor)优化数据库业务负载
本文介绍了Oracle的SQL访问指导(SQL Access Advisor)的应用场景及其使用方法。访问指导通过分析给定的工作负载,提供索引、物化视图和分区等方面的优化建议,帮助DBA提升数据库性能。具体步骤包括创建访问指导任务、创建工作负载、连接工作负载至访问指导、设置任务参数、运行访问指导、查看和应用优化建议。访问指导不仅针对单条SQL语句,还能综合考虑多条SQL语句的优化效果,为DBA提供全面的决策支持。
485 11