sql - 优化 SELECT 查询性能

标签 sql oracle performance optimization view

我有一个 SELECT运行非常缓慢的语句,它阻碍了我们的夜间进程。

查询是:(请不要评论隐式连接语法,这是由运行此代码的 Informatica 自动生成的):

SELECT *
  FROM STG_DIM_CRM_CASES,V_CRM_CASE_ID_EXISTS_IN_DWH,stg_scd_customers_key
 WHERE STG_DIM_CRM_CASES.CRM_CASE_ID = V_CRM_CASE_ID_EXISTS_IN_DWH.CASE_ID(+)
   AND STG_DIM_CRM_CASES.account_number = stg_scd_customers_key.account_number(+)
   and STG_DIM_CRM_CASES.Case_Create_Date between  stg_scd_customers_key.start_date(+) and  stg_scd_customers_key.end_date(+)

编辑 : 实际查询只选择account_number,start_date,end_date和另一列未编入索引。

表信息:

STG_DIM_CRM_CASES
Index - (Account_Number,Case_Create_Date)
size - 270k records.

stg_scd_customers_key
Index - Account_Number,Start_Date,End_Date
Partitioned - End_Date
Size - 500 million records.

V_CRM_CASE_ID_EXISTS_IN_DWH(查看)-
select  t.case_id
from crm_ps_rc_case t, dim_crm_cases x
where t.case_id=x.crm_case_id;

dim_crm_cases -
Indexed - (crm_case_id)
Size - 100 million .

crm_ps_rc_case -
Size - 270k records

编辑 - 如果不清楚,则 View 返回 270k 记录。

没有连接到 stg_scd 的查询需要几秒钟,看起来它是导致性能问题的部分,虽然它正在加入一个 1 亿条记录表,但 View 也在几秒钟内运行。现在查询需要 12 到 30 分钟,这取决于我们的资源有多忙。

这是执行计划:
6   |   0 | SELECT STATEMENT                |                             |  3278K|  1297M|   559K  (4)| 02:10:37 |       |       |        |      |            |
7   |   1 |  PX COORDINATOR                 |                             |       |       |            |          |       |       |        |      |            |
8   |   2 |   PX SEND QC (RANDOM)           | :TQ10003                    |  3278K|  1297M|   559K  (4)| 02:10:37 |       |       |  Q1,03 | P->S | QC (RAND)  |
9   |*  3 |    HASH JOIN OUTER              |                             |  3278K|  1297M|   559K  (4)| 02:10:37 |       |       |  Q1,03 | PCWP |            |
10  |   4 |     PX RECEIVE                  |                             | 29188 |    10M| 50662   (5)| 00:11:50 |       |       |  Q1,03 | PCWP |            |
11  |   5 |      PX SEND HASH               | :TQ10002                    | 29188 |    10M| 50662   (5)| 00:11:50 |       |       |  Q1,02 | P->P | HASH       |
12  |*  6 |       HASH JOIN RIGHT OUTER     |                             | 29188 |    10M| 50662   (5)| 00:11:50 |       |       |  Q1,02 | PCWP |            |
13  |   7 |        BUFFER SORT              |                             |       |       |            |          |       |       |  Q1,02 | PCWC |            |
14  |   8 |         PX RECEIVE              |                             | 29188 |   370K| 50575   (5)| 00:11:49 |       |       |  Q1,02 | PCWP |            |
15  |   9 |          PX SEND BROADCAST      | :TQ10000                    | 29188 |   370K| 50575   (5)| 00:11:49 |       |       |        | S->P | BROADCAST  |
16  |  10 |           VIEW                  | V_CRM_CASE_ID_EXISTS_IN_DWH | 29188 |   370K| 50575   (5)| 00:11:49 |       |       |        |      |            |
17  |* 11 |            HASH JOIN            |                             | 29188 |   399K| 50575   (5)| 00:11:49 |       |       |        |      |            |
18  |  12 |             TABLE ACCESS FULL   | CRM_PS_RC_CASE              | 29188 |   199K|   570   (1)| 00:00:08 |       |       |        |      |            |
19  |  13 |             INDEX FAST FULL SCAN| DIM_CRM_CASES$1PK           |   103M|   692M| 48894   (3)| 00:11:25 |       |       |        |      |            |
20  |  14 |        PX BLOCK ITERATOR        |                             | 29188 |    10M|    87   (2)| 00:00:02 |       |       |  Q1,02 | PCWC |            |
21  |  15 |         TABLE ACCESS FULL       | STG_DIM_CRM_CASES           | 29188 |    10M|    87   (2)| 00:00:02 |       |       |  Q1,02 | PCWP |            |
22  |  16 |     BUFFER SORT                 |                             |       |       |            |          |       |       |  Q1,03 | PCWC |            |
23  |  17 |      PX RECEIVE                 |                             |   515M|    14G|   507K  (3)| 01:58:28 |       |       |  Q1,03 | PCWP |            |
24  |  18 |       PX SEND HASH              | :TQ10001                    |   515M|    14G|   507K  (3)| 01:58:28 |       |       |        | S->P | HASH       |
25  |  19 |        PARTITION RANGE ALL      |                             |   515M|    14G|   507K  (3)| 01:58:28 |     1 |  2982 |        |      |            |
26  |  20 |         TABLE ACCESS FULL       | STG_SCD_CUSTOMERS_KEY       |   515M|    14G|   507K  (3)| 01:58:28 |     1 |  2982 |        |      |            |
27  ------------------------------------------------------------------------------------------------------------------------------------------------------------
28   
29  Predicate Information (identified by operation id):
30  ---------------------------------------------------
31   
32     3 - access("STG_DIM_CRM_CASES"."ACCOUNT_NUMBER"="STG_SCD_CUSTOMERS_KEY"."ACCOUNT_NUMBER"(+))
33         filter("STG_DIM_CRM_CASES"."CASE_CREATE_DATE">="STG_SCD_CUSTOMERS_KEY"."START_DATE"(+) AND 
34                "STG_DIM_CRM_CASES"."CASE_CREATE_DATE"<="STG_SCD_CUSTOMERS_KEY"."END_DATE"(+))
35     6 - access("STG_DIM_CRM_CASES"."CRM_CASE_ID"="V_CRM_CASE_ID_EXISTS_IN_DWH"."CASE_ID"(+))
36    11 - access("T"."CASE_ID"="X"."CRM_CASE_ID")

备注:添加索引可能是一个问题,取决于索引。这不是使用此表的唯一地方,因此索引可能会干扰这些表上的其他命令(主要是插入)。

我还尝试在 stg_scd 上添加过滤器并排除所有小于 Table_Cases 中最小日期的日期,但这并没有帮助,因为它只过滤了 1 年的记录。

提前致谢。

最佳答案

我认为正在发生的是引擎必须在应用限制标准之前将 100m+ 记录从 View 连接解析为 500m 记录(因此它创建了一个交叉连接,即使它可以使用生成大量记录的索引然后解析. 所以即使你把它写成一个外连接,引擎也不能那样处理它(我不知道为什么)

因此,至少 100m*500m = 50,000m 需要生成大量数据然后解析/限制。

通过消除 View ,引擎可能能够更好地优化和使用索引,从而消除对 50,000m 记录连接的需要。

我会集中时间进行故障排除的领域:

  • 消除 View 只是为了将其作为潜在的开销问题删除。
  • 识别 stg_scd_customers_key 和 V_CRM_CASE_ID_EXISTS_IN_DWH 之间不存在关联。这意味着引擎可能会在结果之前进行交叉连接
    STG_DIM_CRM_CASES 到 stg_scd_customers_key 已解决。

  • 考虑消除 View ,或使用内联 View

    消除 View :
    SELECT *
      FROM STG_DIM_CRM_CASES 
          ,crm_ps_rc_case t
          ,dim_crm_cases x 
          ,stg_scd_customers_key
     WHERE t.case_id=x.crm_case_id
       AND STG_DIM_CRM_CASES.CRM_CASE_ID = t.CASE_ID(+)
       AND STG_DIM_CRM_CASES.account_number = stg_scd_customers_key.account_number(+)
       AND STG_DIM_CRM_CASES.Case_Create_Date 
           between  stg_scd_customers_key.start_date(+) and stg_scd_customers_key.end_date(+)
    

    使用内联 View :
    SELECT *
      FROM STG_DIM_CRM_CASES 
      (select  t.case_id
       from crm_ps_rc_case t, dim_crm_cases x
       where t.case_id=x.crm_case_id) V_CRM_CASE_ID_EXISTS_IN_DWH
          ,stg_scd_customers_key
     WHERE STG_DIM_CRM_CASES.CRM_CASE_ID = V_CRM_CASE_ID_EXISTS_IN_DWH.CASE_ID(+)
       AND STG_DIM_CRM_CASES.account_number = stg_scd_customers_key.account_number(+)
       AND STG_DIM_CRM_CASES.Case_Create_Date 
           between  stg_scd_customers_key.start_date(+) and stg_scd_customers_key.end_date(+)
    

    至于为什么:
    - http://www.dba-oracle.com/art_hints_views.htm

    虽然 where 子句的顺序不应该考虑:在关闭追逐时,引擎按照列出的顺序执行,限制 500m,然后从 View 中添加补充数据在逻辑上会更快。
    SELECT *
      FROM STG_DIM_CRM_CASES,stg_scd_customers_key,V_CRM_CASE_ID_EXISTS_IN_DWH
     WHERE STG_DIM_CRM_CASES.account_number = stg_scd_customers_key.account_number(+)
       and STG_DIM_CRM_CASES.Case_Create_Date between  stg_scd_customers_key.start_date(+) and  stg_scd_customers_key.end_date(+)
       and STG_DIM_CRM_CASES.CRM_CASE_ID = V_CRM_CASE_ID_EXISTS_IN_DWH.CASE_ID(+)
    

    关于sql - 优化 SELECT 查询性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38613118/

    相关文章:

    java - 无法使用 Java/JSP 将数据插入 Apache Derby 数据库

    sql - Grails:HasMany交集查询

    oracle - ORACLE PL/SQL 中有计算多边形面积的函数吗?

    mysql - 性能套接字 nodejs + mysql

    performance - 限制WebSocket的网络速度

    sql - 查询顺序

    sql - 如何获取具有最大值的行并且它与其他两个表相匹配?

    oracle - 如何将oracle转储从ec2实例导入到AWS中的RDS

    oracle - JDBC 连接失败并出现 ORA-12516

    mysql - 极慢的MySQL性能