执行速度非常慢的SQL case-expression(查询优化)

时间:2018-03-27 12:21:28

标签: sql oracle performance query-optimization

我得到了这个小代码,这实际上有点长,但是我已经创建了一些临时工作表来加速测试而不是运行"用"每时每刻。查询运行时可以考虑行数,直到下面显示的部分。我已经制作了两个临时表," disc_memberlist"和billing_disc。我想比较两者,并添加一个列,说明用户是否存在于billing_disc中(Y和N,在这种情况下)如果我指定一个预先确定的agreement_id,则select工作正常。但是,如果我删除它,并希望它遍历所有行,它会磨成一个爬行。每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)"

2 个答案:

答案 0 :(得分:0)

我建议使用三个表(LEFT JOIN)创建一个临时表。不要忘记使用procedure analyse索引并创建正确的变量。同时尝试EXPLAIN查询,它会为您提供有关如何提高性能的更多提示。

答案 1 :(得分:0)

您应该使用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;