您好,欢迎访问一九零五行业门户网

性能陷阱:Oracle表连接中范围比较

lately, i met a case that the range filter predicates due to wrong cardinality issue. letrsquo;s check the followin
lately, i met a case that the range filter predicates due to wrong cardinality issue. let’s check the following query.
最近遇到一个由于范围过滤导致错误基数而引起的性能问题。让我们来看下面的查询:
the real records number is around 38,000,000.
真实的记录数大约3千8百万
the explain plan shows 72838, optimizer think it has good filtration. so put this join in the first order. actually , it is totally wrong.
执行计划显示72838,这里优化器认为它有良好的过滤芯,所以把它放在一个多个表join的第一位置。显然,,它完全错了。
sql> set autotrace traceonly explain;
sql> set linesize 999
sql> select
2   t.durationsecsqty timeinseconds,
t.moneyamt moneyamount,
t.wageamt wageamount,
t.applydtm applydate,
t.adjapplydtm adjustedapplydate,
t.startdtm,
t.enddtm,
t.homeaccountsw
from
tkcsowner.wfctotal     t,
tkcsowner.paycode1mmflat mp
where
mp.effectivedtm
and mp.expirationdtm > t.applydtm
and mp.paycodeid = t.paycodeid
/
---------------------------------------------------------------------
| id | operation       | name       | rows | bytes | cost |
---------------------------------------------------------------------
|   0 | select statement   |           | 72838 | 5192k| 37450 |
|* 1 | hash join       |           | 72838 | 5192k| 37450 |
|   2 |   table access full| paycode1mmflat |   323 | 6783 |   3 |
|   3 |   table access full| wfctotal     | 8938k|   443m| 37317 |
now, let me comment the range filter.
让我注释到范围条件看:
“mp.effectivedtm
and mp.expirationdtm > t.applydtm”
sql> select
2   t.durationsecsqty timeinseconds,
t.moneyamt moneyamount,
t.wageamt wageamount,
t.applydtm applydate,
t.adjapplydtm adjustedapplydate,
t.startdtm,
t.enddtm,
t.homeaccountsw
from
tkcsowner.wfctotal     t,
tkcsowner.paycode1mmflat mp
where
/*   mp.effectivedtm
and mp.expirationdtm > t.applydtm*/
mp.paycodeid = t.paycodeid 3   4   5   6   7   8   9   10   11   12   13   14   15   16
17 /
execution plan
----------------------------------------------------------
plan hash value: 564403449
---------------------------------------------------------------------------
| id | operation         | name         | rows | bytes | cost |
---------------------------------------------------------------------------
|   0 | select statement     |             |   29m| 1583m| 37405 |
|* 1 | hash join         |             |   29m| 1583m| 37405 |
|   2 |   index fast full scan| pk_paycode1mmflat |   323 | 1615 |   1 |
|   3 |   table access full   | wfctotal       | 8938k|   443m| 37317 |
the cardinality show 29,135,142 , it is already close to the correct value.
基础是29,135,142,已经接近正确结果了。
so how optimizer work out the cardinality with range filter in table join ?
那么优化器怎么出来表连接中的范围扫描呢?
the answer is 5%, always 5%.
答案是5%
29135142 * 5% * 5% = 72837.8 , this is exact equal to the result of test 1.
so if you meet any performance issue with range filter in tbale join, i am not surprise. i think oracle need to improve the cbo to get better support on such situation.
其它类似信息

推荐信息