【问题标题】:SQL cross join query slower than expected, refactoring ideas neededSQL交叉连接查询比预期慢,需要重构思路
【发布时间】:2013-03-04 21:14:18
【问题描述】:

此查询有效,但需要 5000 毫秒。

SELECT 
    SUM(case 
        when ((TRUNC(OPEN_DATE) <= thedate and TRUNC(END_DATE) > thedate) or(TRUNC(OPEN_DATE) <= thedate and END_DATE Is Null)) then 1 
        else 0 
        end) as Open  
From ( 
    select * 
    FROM PROJECT 
    WHERE 
        PROGRAM_NAME = :program   
        AND ACTION_FOR_ORG = :orgName 
    )   
    cross join ( 
        select add_months(last_day(SYSDATE), level-7) as thedate 
        from dual 
        connect by level <= 12  
    )  
GROUP BY thedate
ORDER BY thedate

如果我将子查询复制到自己的表中

create table test_project as  
select * FROM PROJECT WHERE PROGRAM_NAME = :program   
AND ACTION_FOR_ORG = :orgName

然后执行上述查询,但子查询在复制的表上为:

From ( select * FROM test_project WHERE PROGRAM_NAME = :program   
AND ACTION_FOR_ORG = :orgName ) 

查询需要 10 毫秒

根据OPEN_DATEEND_DATE 的比较,查询产生了过去 5 个月和未来几个月中该月开放项目的数量(未来几个月的开放项目数量将等于今天月份的总数)

有没有办法重写原始查询以获得最佳性能?

编辑

好的,我创建了第二个表,它是我被允许访问的项目表(井视图)的完整副本。表格复制大约需要 5 秒。使用完整的数据集和我的 sql 查询或来自下面的 Egor,查询速度非常快。视图有问题。尝试使用子查询中的视图吐出解释计划,但权限不足。这是使用完整视图副本的解释计划

 Plan hash value: 3695211866

 ------------------------------------------------------------------------------------------------
 | Id  | Operation                        | Name        | Rows  | Bytes | Cost (%CPU)|     Time     |
 ------------------------------------------------------------------------------------------------
 |   0 | SELECT STATEMENT                 |             |   637 |  1277K|   163   (2)| 00:00:02 |
 |   1 |  SORT ORDER BY                   |             |   637 |  1277K|   163   (2)| 00:00:02 |
 |   2 |   HASH GROUP BY                  |             |   637 |  1277K|   163   (2)| 00:00:02 |
 |   3 |    MERGE JOIN CARTESIAN          |             |   637 |  1277K|   161   (0)| 00:00:02 |
 |   4 |     VIEW                         |             |     1 |     6 |     2   (0)| 00:00:01 |
 |*  5 |      CONNECT BY WITHOUT FILTERING|             |       |       |              |          |
 |   6 |       FAST DUAL                  |             |     1 |       |     2   (0)| 00:00:01 |
 |   7 |     BUFFER SORT                  |             |   637 |  1273K|   163   (2)| 00:00:02 |
 |*  8 |      TABLE ACCESS FULL           | COMMIT_TEST |   637 |  1273K|   159   (0)| 00:00:02 |

谓词信息(由操作id标识):


5 - filter(LEVEL<=12)
8 - filter("PROGRAM_NAME"='program_name' AND "ACTION_FOR_ORG"='action_for_org')

注意


- dynamic sampling used for this statement (level=2)

使用活动表解释计划

【问题讨论】:

  • “如果我将子查询复制到自己的表中”..创建该表需要多长时间?你能发布原始查询的解释计划吗?
  • 不确定创建需要多长时间,但查询需要 220 毫秒来执行“select * FROM PROJECT WHERE PROGRAM_NAME = :program AND ACTION_FOR_ORG = :orgName”。我如何获得解释计划?我正在使用 Eclipse DataTools 插件来运行 sql 便笺簿。我安装了 SQL Plus,但并没有真正使用它
  • 我想出了如何生成解释计划,但是我得到“视图底层对象的权限不足”
  • "表格复制耗时约 5 秒。"因此,涉及基本视图而不是副本的所有查询变体所花费的时间是扫描视图中涉及的表。在视图中,program_nameaction_for_org 在同一个基表上吗?如果是这样,它们上是否有可用的复合索引(您应该运行以视图所有者身份失败的解释计划,以免出现权限错误)
  • 添加了解释计划。看起来 program_name 不在基表中

标签: oracle database-performance


【解决方案1】:
with
   PRJ as (
      select /*+ NO_UNNEST */ 
         trunc(OPEN_DATE) as OPEN_DATE,
         nvl(trunc(END_DATE), sysdate + 1000) as END_DATE
      from
         PROJECT
      where
         PROGRAM_NAME = :program
         and ACTION_FOR_ORG = :orgName
   ),
   DATES as (
      select
         add_months(trunc(last_day(SYSDATE)), level-7) as thedate
      from dual
      connect by level <= 12
   )
SELECT
   thedate,
   sum(case when thedate between open_date and end_date then 1 end) as Open
FROM
   DATES, PRJ
GROUP BY thedate
ORDER BY 1

【讨论】:

  • 您的查询看起来很干净,但仍需要 5011 毫秒。 PROJECT 是允许我访问的视图是否重要?
  • @jeff - 试试PUSH_SUBQ 提示。
  • 5091 毫秒。使用 PUSH_SUBQ。我对这些提示不熟悉,但我认为我正确地应用了它们。我正在使用 Eclipse Datatools 来测试 sql 查询,然后再将它们应用到我的 Java Web 应用程序中,该应用程序绘制了打开的项目。我认为用户会因为等待 5 秒而得到一个简单的图表而感到沮丧。我需要在 SQL+ 中运行它并获得解释计划。接下来会尝试解决这个问题。
  • 如果我将带有 UNIQUE 的子查询放在第一个选择中,它会下降到 1000 毫秒。 "nvl(trunc(END_DATE), sysdate + 1000) as END_DATE from (SELECT UNIQUE * from PROJECT where PROGRAM_NAME = :program and ACTION_FOR_ORG = :orgName)), DATES ..."
猜你喜欢
  • 1970-01-01
  • 2019-03-03
  • 2012-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-14
  • 2020-04-27
  • 2015-07-26
相关资源
最近更新 更多