【问题标题】:how to reduce the cost of the below query如何降低以下查询的成本
【发布时间】:2022-01-14 02:14:21
【问题描述】:
SELECT
    *
FROM
    xxcpb_i45_06_interface_r
WHERE
    trunc(creation_date) < trunc(sysdate) - 2
    AND ( ( request_id < (
        SELECT
            MAX(xcs_sub.request_id)
        FROM
            xxcpb_i45_06_interface_r xcs_sub
        WHERE
            xcs_sub.status = 'PROCESSED'
            AND xcs_sub.file_id = 'CBS1330'
    )
            AND file_id = 'CBS1330' )
          OR ( request_id < (
        SELECT
            MAX(xcs_sub.request_id)
        FROM
            xxcpb_i45_06_interface_r xcs_sub
        WHERE
            xcs_sub.status = 'PROCESSED'
            AND xcs_sub.file_id = 'CCI1330'
    )
               AND file_id = 'CCI1330' ) )
  • 说明计划显示成本 = 37061
  • 我尝试在 where 子句中使用但不起作用的列上创建索引。

【问题讨论】:

  • Cost 只是 IMO 不是调整的最佳起点。显示完整的execution plan 和有关您的表的其他信息(如果它是表而不是视图),以便提供更有针对性的答案;不是一个糟糕的猜测。
  • 我们不知道您的标准有多严格。 trunc(creation_date) &lt; trunc(sysdate) - 2 可以优化为creation_date &lt; trunc(sysdate) - 2。而且这似乎会影响表中的几乎所有行(除了最近三天之外的所有行)。表中通常有多少天?然后,您只考虑文件 ID CBS1330 和 CCI1330。表中有多少个不同的文件 ID?最后,有多少百分比的行状态为 PROCESSED?表格有多少行?您希望查询返回多少行?
  • “成本”只是优化器用来比较给定语句的几种可能访问计划的预期性能的人造数字。如果您的查询没有像您希望的那样快速运行,请忘记查看“成本”并专注于 EXPLAIN PLAN 以及可能的 sql 跟踪以查看时间的去向。并考虑甚至可以挤出多少。如果查询已经以亚秒级的速度运行,那么将时间减少 50% 需要付出多少努力?

标签: sql oracle query-optimization


【解决方案1】:

你可以:

  • 使用分析函数而不是子查询。
  • TRUNC(creation_date) 周围删除TRUNC,好像截断的日期小于TRUNC(SYSDATE) - 2,那么它也将始终为真而不会截断。这将让优化器使用creation_date 列上的索引(而不是要求TRUNC(creation_date) 上的基于函数的索引)。

这会给你:

SELECT *
FROM   (
  SELECT x.*,
         MAX(
           CASE
           WHEN status = 'PROCESSED'
           AND  file_id = 'CBS1330'
           THEN request_id
           END
         ) OVER () AS max_processed_cbs,
         MAX(
           CASE
           WHEN status = 'PROCESSED'
           AND  file_id = 'CCI1330'
           THEN request_id
           END
         ) OVER () AS max_processed_cci
  FROM   xxcpb_i45_06_interface_r x
  WHERE  file_id IN ('CBS1330', 'CCI1330')
)
WHERE  creation_date < TRUNC(SYSDATE) - 2
AND    (  (file_id = 'CBS1330' AND request_id < max_processed_cbs)
       OR (file_id = 'CCI1330' AND request_id < max_processed_cci)
       );

那么你可以考虑在你正在使用的列上添加索引。

【讨论】:

  • 使用上述查询后 - 解释显示高基数和成本几乎相同但时间将减少 2 秒的计划。
  • @W_O_L_F SQL 引擎几乎肯定会同等对待两者;您可以使用EXPLAIN PLAN 来检查是否有任何差异。
【解决方案2】:

您可以尝试添加此索引(如果首先添加索引是一个选项):

create index test_index on xxcpb_i45_06_interface_r(file_id, request_id, status)

【讨论】:

  • 为file_id、request_id、creation_date和status列添加索引已经创建索引。创建索引后有执行解释计划但成本不会降低。
【解决方案3】:
SELECT
        tr.* 
FROM
    xxcpb_i45_06_interface_r tr
join (
        SELECT
            xcs_sub.file_id, MAX(xcs_sub.request_id) request_id 
        FROM
            xxcpb_i45_06_interface_r xcs_sub
        WHERE
              xcs_sub.status = 'PROCESSED'
          AND xcs_sub.file_id in ('CCI1330', 'CBS1330')
        group by xcs_sub.file_id

    )t on t.request_id > tr.request_id 
      and tr.file_id =  t.file_id
where 
      creation_date < trunc(sysdate) - 2;

【讨论】:

  • thnx,运行此查询后,它需要更多时间,并且在解释计划中显示成本也增加了。我们希望减少查询的成本和时间,使其运行得更快,成本应该最低
  • @Aishwarya 添加有关您餐桌的更多信息。
  • 您需要了解有关表的哪些确切信息
  • @Aishwarya 行数、索引,还需要查询计划。
猜你喜欢
  • 2022-01-15
  • 2019-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-16
  • 2022-01-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多