Oracle 计划比较“b”和“b”与“B”相对慢 998 倍(10g 或 11g)

发布于 2024-12-21 15:56:50 字数 2505 浏览 2 评论 0原文

通过与另一个表进行比较来查询将记录设置为坏记录。为了节省时间,我排除了已标记为“不良”的记录。

我编写了一个查询,但意外地检查了 != 'b' 而不是 != 'B'...查询在 0.203 秒内执行。当我意识到自己的错误时,我将其更改为 != 'B',但是现在查询需要超过 200 秒才能执行!

当我检查计划时,“b”的优化器选择两个散列连接的串联。 “B”的计划选择嵌套循环。

如果重要的话,我的测试中没有任何标记为“B”的记录。 gsu.stg_userdata 中有约 18,000 条记录,gsu.userdata_compare 中有约 73,000 条记录。两个查询都会得出相同(且正确)数量的结果。


查询:

select gstgu.global_id
from   gsu.stg_userdata gstgu
  left join gsu.userdata_compare guc
    on (gstgu.global_id = guc.global_id) or (gstgu.user_id = guc.user_id)
where  gstgu.row_check != 'b' 
   and ((-- Global IDs match, but two different Network IDs are explicitly set
         (gstgu.global_id = guc.global_id) and (guc.user_id is not null and 
                                                gstgu.user_id is not null and
                                                guc.user_id != gstgu.user_id))
         -- Network IDs match, but two different Global IDs are explicitly set
      or (guc.user_id = gstgu.user_id and (guc.global_id is not null and 
                                           gstgu.global_id is not null and
                                           guc.global_id != gstgu.global_id))
      or length(gstgu.global_id) != 8)
   and guc.global_id != '00000000';

--


这个sql的计划:

                                                 Cost   Card   Bytes
SELECT STATEMENT, GOAL = ALL_ROWS                1014   1410   49350
 CONCATENATION          
  HASH JOIN                                       507    559   19565
   TABLE ACCESS FULL       GSU  STG_USERDATA      205  11144  189448
   INDEX FAST FULL SCAN    GSU  USERCOMPARE_IDX   302  16979  305622
  HASH JOIN                                       507    851   29785
   INDEX FAST FULL SCAN    GSU  USERCOMPARE_IDX   302  16979  305622
   TABLE ACCESS FULL       GSU  STG_USERDATA      205  17949  305133


如果我采用完全相同的查询,并说

where  gstgu.row_check != 'B' 

执行时间超过 200 秒(几乎是 1,000 倍),并且计划如下所示:

                                                 Cost   Card   Bytes
SELECT STATEMENT, GOAL = ALL_ROWS                 507      1      35
 NESTED LOOPS                                     507      1      35
  TABLE ACCESS FULL        GSU  STG_USERDATA      205      1      17
  INDEX FAST FULL SCAN     GSU  USERCOMPARE_IDX   302      1      18


我快要疯了,这是什么原因?

Have a query to set records as bad by comparing with another table. To save time, I exclude records that have already been marked as 'bad'.

I wrote a query, but accidentally checked for != 'b' instead of != 'B'... the query executed in 0.203 seconds. When I realized my mistake, I changed it to != 'B', but now the query takes more than 200 seconds to execute!!!

When I checked the plans, the optimizer for 'b' chooses a concatenation of two hash joins. The plan for 'B' chooses nested loops.

If it matters, there aren't any records marked as 'B' for my test. There are ~18,000 records in gsu.stg_userdata, and ~ 73,000 records in gsu.userdata_compare. Both queries come up with the same (and correct) number of results.

The query:

select gstgu.global_id
from   gsu.stg_userdata gstgu
  left join gsu.userdata_compare guc
    on (gstgu.global_id = guc.global_id) or (gstgu.user_id = guc.user_id)
where  gstgu.row_check != 'b' 
   and ((-- Global IDs match, but two different Network IDs are explicitly set
         (gstgu.global_id = guc.global_id) and (guc.user_id is not null and 
                                                gstgu.user_id is not null and
                                                guc.user_id != gstgu.user_id))
         -- Network IDs match, but two different Global IDs are explicitly set
      or (guc.user_id = gstgu.user_id and (guc.global_id is not null and 
                                           gstgu.global_id is not null and
                                           guc.global_id != gstgu.global_id))
      or length(gstgu.global_id) != 8)
   and guc.global_id != '00000000';

--

The plan for this sql:

                                                 Cost   Card   Bytes
SELECT STATEMENT, GOAL = ALL_ROWS                1014   1410   49350
 CONCATENATION          
  HASH JOIN                                       507    559   19565
   TABLE ACCESS FULL       GSU  STG_USERDATA      205  11144  189448
   INDEX FAST FULL SCAN    GSU  USERCOMPARE_IDX   302  16979  305622
  HASH JOIN                                       507    851   29785
   INDEX FAST FULL SCAN    GSU  USERCOMPARE_IDX   302  16979  305622
   TABLE ACCESS FULL       GSU  STG_USERDATA      205  17949  305133

If I take the exact same query, and say

where  gstgu.row_check != 'B' 

it takes more than 200 seconds to execute (nearly 1,000x as long) and the plan looks like:

                                                 Cost   Card   Bytes
SELECT STATEMENT, GOAL = ALL_ROWS                 507      1      35
 NESTED LOOPS                                     507      1      35
  TABLE ACCESS FULL        GSU  STG_USERDATA      205      1      17
  INDEX FAST FULL SCAN     GSU  USERCOMPARE_IDX   302      1      18

I'm going crazy, what gives??

.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

春庭雪 2024-12-28 15:56:50

向 Row_check 字段添加索引...大多数时候这个问题就是由此引起的。

add an index to Row_check field .... most of the times this issue is caused by this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文