【问题标题】:SQL Help- in rewriting a querySQL 帮助 - 重写查询
【发布时间】:2017-12-12 21:42:15
【问题描述】:

我们怎样才能减少下面查询的执行时间?

需要帮助以更有效的方式重写以下 SQL 查询?

SELECT A.*, C.*, F.*, D.*
FROM TABLE1 A  INNER JOIN
     TABLE2 C
     ON A.CODE = C.CODE INNER JOIN
     TABLE3 D
     ON A.CODE = D.CODE INNER JOIN
     TABLE4 F
     ON A.CODE = F.CODE
WHERE D.IND1 = 'N' AND
      D.IND2 = 'N' AND
      D.EFF_DATE = (SELECT MAX(X.EFF_DATE)
                    FROM TABLE3 X
                    WHERE X.CODE = D.CODE AND X.EFF_DATE <= A.EFFECTIVE_DATE
                   ) AND
      F.EFF_DATE = (SELECT MAX(Z.EFF_DATE)
                    FROM TABLE4 Z
                    WHERE Z.DETAIL_CODE = F.DETAIL_CODE AND Z.EFF_DATE <= A.EFFECTIVE_DATE
                   )

【问题讨论】:

  • 我认为如果您提供示例数据集,您将获得更快、更有效的答案。通常,人们使用sqlfiddle.com 来提供这些集合。
  • 你没有提供样本数据,没有执行计划,没有数据模型,没有解释业务规则,没有数据量或倾斜的指标,没有关于索引、统计等的信息。我们无法就重写此查询给您任何有意义的建议。

标签: sql oracle performance query-optimization


【解决方案1】:

为了性能,我会从以下索引开始:

  • TABLE3(IND1, IND2, CODE, EFF_DATE)
  • TABLE3(CODE, EFF_DATE)
  • TABLE1(CODE, EFF_DATE)
  • TABLE2(CODE)
  • TABLE4(CODE)
  • TABLE4(DETAIL_CODE, EFF_DATE)

不过,如果您遇到性能问题,我怀疑您的代码可能会生成意外的笛卡尔积。需要更多信息的调试。我可能建议再问一个问题。

【讨论】:

    【解决方案2】:

    如果您能找出查询中的瓶颈在哪里——即子查询、连接——这将使您更好地了解要查看的内容。如果没有,请看一下:

    如果您可以提供 EXPLAIN 计划(或 Oracle 的等效计划),那将很有帮助。

    【讨论】:

      【解决方案3】:

      请注意,由于两个子查询的条件,结果中的所有记录都会有D.EFF_DATE &lt;= A.EFFECTIVE_DATEF.EFF_DATE &lt;= A.EFFECTIVE_DATE,所以我建议将这些条件放在JOIN 子句中。

      其次,分析函数可能比子查询提供更好的性能:

      SELECT *
      FROM (
        SELECT      A.*,C.*,F.*,D.*,
                    RANK() OVER (PARTITION BY D.CODE 
                                 ORDER BY D.EFF_DATE DESC) AS D_RANK,
                    RANK() OVER (PARTITION BY F.DETAIL_CODE 
                                 ORDER BY F.EFF_DATE DESC) AS F_RANK
        FROM        TABLE1 A
        INNER JOIN  TABLE2 C
                 ON A.CODE = C.CODE
        INNER JOIN  TABLE3 D
                 ON A.CODE = D.CODE
                AND D.EFF_DATE <= A.EFFECTIVE_DATE
        INNER JOIN  TABLE4 F
                 ON A.CODE = F.CODE
                AND F.EFF_DATE <= A.EFFECTIVE_DATE
        WHERE       D.IND1 = 'N'
                AND D.IND2 = 'N'
      )
      WHERE D_RANK = 1 AND F_RANK = 1
      

      显然你需要有正确的索引来优化执行计划。

      【讨论】:

      • 感谢您的回复。如果我有多个代码和有效日期对(重复),如何使用排名将其限制为仅一条记录?
      • 在这种情况下使用row_number() 而不是rank()。但是您的原始查询将对应于使用rank
      【解决方案4】:

      要考虑的另一件事是查询返回的总列数,您似乎从 4 个表中选择了所有列。

      我们发现,我们的复杂查询在仅选择几列时运行时间不到一秒,但在选择多列时需要更长的时间。

      问为什么您的结果集中需要这么多列。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-14
        • 2010-10-20
        • 1970-01-01
        相关资源
        最近更新 更多