Oracle 计划比较“b”和“b”与“B”相对慢 998 倍(10g 或 11g)
通过与另一个表进行比较来查询将记录设置为坏记录。为了节省时间,我排除了已标记为“不良”的记录。
我编写了一个查询,但意外地检查了 != '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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
向 Row_check 字段添加索引...大多数时候这个问题就是由此引起的。
add an index to Row_check field .... most of the times this issue is caused by this.