执行 SQL 案例表达式非常慢(查询优化)

Posted

技术标签:

【中文标题】执行 SQL 案例表达式非常慢(查询优化)【英文标题】:Very slow performing SQL case-expression (query optimization) 【发布时间】:2018-03-27 12:21:28 【问题描述】:

我得到了这个小代码,实际上要长得多,但我创建了一些临时工作表来加速测试,而不是一直运行“with”。查询运行正常,考虑的行数,直到下面显示的部分。我已经制作了两个临时表,“disc_memberlist”和 billing_disc。我想比较两者,并添加一个列,说明用户是否存在于 billing_disc 中(在这种情况下是 Y 和 N)如果我指定了预先确定的协议 ID,则选择工作正常。但是,如果我将其删除,并希望它遍历所有行,它就会爬行。每 10 秒 200 行(我需要解析一百万行)

有什么建议可以让我以更好的性能实现这一目标吗?

SELECT 
          dm.user_id
          ,dm.agreement_id
          ,dm.cust_id
          ,dm.offer_id
          ,dm.offer_type
          ,dm.resource_spec_id
          ,dm.memberlist_subscriber_count
          ,CASE
              WHEN dm.user_id in (SELECT user_id      
FROM   disc_memberlist dm
WHERE  dm.user_id IN (SELECT bd.resource_id
                          FROM  billing_disc bd )) 
                  THEN
             'Y'
             ELSE
             'N'
      END AS Exists_in_billing

执行计划是

"PLAN_TABLE_OUTPUT"
"Plan hash value: 3054186447"
" "
"------------------------------------------------------------------------------------------------"
"| Id  | Operation          | Name                      | Rows  | Bytes | Cost (%CPU)| Time     |"
"------------------------------------------------------------------------------------------------"
"|   0 | SELECT STATEMENT   |                           |  1727K|    87M|    21G  (1)|232:59:10 |"
"|*  1 |  HASH JOIN SEMI    |                           |     1 |    18 | 12480   (1)| 00:00:01 |"
"|*  2 |   TABLE ACCESS FULL| AGREEMENT_MEMBERLIST_KRPS |     1 |     9 |  3896   (1)| 00:00:01 |"
"|*  3 |   TABLE ACCESS FULL| BILLING_DISC_KRPS         |    30 |   270 |  8585   (1)| 00:00:01 |"
"|   4 |  TABLE ACCESS FULL | AGREEMENT_MEMBERLIST_KRPS |  1727K|    87M|  3899   (1)| 00:00:01 |"
"------------------------------------------------------------------------------------------------"
" "
"Predicate Information (identified by operation id):"
"---------------------------------------------------"
" "
"   1 - access(""DM"".""USER_ID""=""BD"".""RESOURCE_ID"")"
"   2 - filter(""USER_ID""=:B1)"
"   3 - filter(""BD"".""RESOURCE_ID""=:B1)"

【问题讨论】:

可以分享一下执行计划吗? 【参考方案1】:

您应该使用LEFT JOIN 而不是IN。如果您在 disc_memberlist.user_idbilling_disc.resource_id 列上有正确的索引,它应该会提高性能,因为它不会在您的表中进行完整扫描。

SELECT 
    dm.user_id
    ,dm.agreement_id
    ,dm.cust_id
    ,dm.offer_id
    ,dm.offer_type
    ,dm.resource_spec_id
    ,dm.memberlist_subscriber_count
    ,NVL2(bd.resource_id, 'Y', 'N') AS Exists_in_billing
FROM disc_memberlist dm
LEFT JOIN billing_disc bd ON dm.user_id = bd.resource_id;

【讨论】:

【参考方案2】:

我建议使用三个表创建一个临时表 (LEFT JOIN)。不要忘记使用procedure analyse 索引和创建正确的变量。也可以尝试EXPLAIN查询,它会给你更多关于如何提高性能的提示。

【讨论】:

以上是关于执行 SQL 案例表达式非常慢(查询优化)的主要内容,如果未能解决你的问题,请参考以下文章

Oracle优化案例 | 从执行计划定位SQL查询问题

Oracle优化案例 | 从执行计划定位SQL查询问题

分享一则sql优化案例:生产数据库从385s优化到16.8s

SQL语句常见优化十大案例

Mysql优化之慢查询优化

需要帮助优化涉及数百万条记录的非常慢的 DB2 SQL 查询