【问题标题】:ORACLE QUERY - OPTIMISATIONORACLE 查询 - 优化
【发布时间】:2015-02-26 17:12:30
【问题描述】:

我已经编写了下面的查询,它有很多“AND”运算符,我想知道如何优化下面查询的性能[我可以删除一些“AND”运算符吗]

    SELECT I.date,
              K.somcolumn,
              L.somcolumn,
              D.somcolumn
         FROM Table1 I,
              Table2 K,
              Table3 L,
              Table4 D
        WHERE I._ID = K._ID
              AND K.ID = L._ID
              AND L._ID = I._ID
              AND I._CODE = L._CODE
              AND K.ID = D._ID(+)
              AND L._ID IN ( SELECT _id
                                       FROM I
                                      WHERE UPPER (someflag) = 'TRUE'
                                   GROUP BY _id
                                     HAVING COUNT (*) > 1)
              AND L._ID IN ( SELECT _id
                                       FROM I
                                      WHERE UPPER (code) = 'OPEN'
                                   GROUP BY _id
                                     HAVING COUNT (*) > 1)
     ORDER BY I._ID, I._CODE;

【问题讨论】:

  • 如果返回的行数很少,您可以尝试使用标量子查询将表 I 中的计数作为新返回的列。您也可以尝试使用 WITH 子句从表 I 构建临时表。只是想法。我无法给出答案,因为我无法验证我的想法。
  • 另外,使用EXISTS 可能比IN 快得多,因为可以使用索引。 EXISTS ( SELECT NULL FROM I WHERE L._id=_id AND UPPER(code) = 'OPEN' GROUP BY _id HAVING COUNT (*) > 1)。因为索引可能用于 _id 代码,而 someflag 可能是位图索引的候选对象。

标签: oracle oracle11g oracle10g oracle-sqldeveloper


【解决方案1】:

据我所知,您无法组合任何条件,但您可以使用标准 JOIN 语法改进查询并减少 AND 运算符的数量:

SELECT I.date,
  K.somcolumn,
  L.somcolumn,
  D.somcolumn
FROM Table1 I
INNER JOIN Table2 K ON I._ID = K._ID
INNER JOIN Table3 L ON K.ID = L._ID
LEFT JOIN Table4 D ON K.ID = D._ID
WHERE L._ID IN ( SELECT _id
   FROM I
   WHERE UPPER (someflag) = 'TRUE'
   GROUP BY _id
   HAVING COUNT (*) > 1)
 AND L._ID IN ( SELECT _id
   FROM I
   WHERE UPPER (code) = 'OPEN'
   GROUP BY _id
   HAVING COUNT (*) > 1)
ORDER BY I._ID, I._CODE;

以此为基础,如果您加入子查询条件而不是使用相关子查询,您可能会获得优化提升。没有保证,但这样的事情可能会有所帮助:

SELECT I.date,
  K.somcolumn,
  L.somcolumn,
  D.somcolumn
FROM Table1 I
INNER JOIN Table2 K ON I._ID = K._ID
INNER JOIN Table3 L ON K.ID = L._ID
LEFT JOIN Table4 D ON K.ID = D._ID
INNER JOIN (
    SELECT _id
    FROM I
    WHERE UPPER (someflag) = 'TRUE'
    GROUP BY _id
    HAVING COUNT (*) > 1
  ) someflagtrue ON L._ID = someflagtrue._id
INNER JOIN (
    SELECT _id
     FROM I
     WHERE UPPER (code) = 'OPEN'
     GROUP BY _id
     HAVING COUNT (*) > 1
  ) codeopen ON L._ID = codeopen._id
ORDER BY I._ID, I._CODE;

【讨论】:

    【解决方案2】:

    您可以将两个子查询替换为一个。

    旧的子查询:

      SELECT _id
        FROM I
       WHERE UPPER (someflag) = 'TRUE'
    GROUP BY _id
      HAVING COUNT (*) > 1)
    
      SELECT _id
        FROM I
       WHERE UPPER (code) = 'OPEN'
    GROUP BY _id
      HAVING COUNT (*) > 1)
    

    新的子查询:

    SELECT _ID
      FROM I
     GROUP BY _ID
    HAVING COUNT(CASE WHEN UPPER(SOMEFLAG) = 'TRUE' THEN 1 ELSE 0 END) > 0
       AND COUNT(CASE WHEN UPPER(CODE) = 'OPEN' THEN 1 ELSE 0 END) > 0
    

    在大多数情况下,这至少应该快一点,因为它可能会减少全表扫描和连接的次数。但是很难判断它在您的系统上是否会更快,因为优化器有很多可能的选择。

    清理查询后,性能调整的下一步是生成解释计划。运行explain plan for select ...;,然后运行select * from table(dbms_xplan.display);,这将向您展示查询是如何执行的,这可能会提示您哪些地方慢,哪些地方可以改进。如果您需要更多帮助,请将解释计划的完整输出添加到您的问题中。它还可能有助于添加有关相关表中的行数、返回的行数以及索引是什么的信息。

    【讨论】:

      猜你喜欢
      • 2011-01-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多