oracle的hint很多人都知道,那原理是什么呢?在系统中该不该用呢?先来做个试验:
create table test1 as select * from dba_objects where rownum <=100;
create table test2 as select * from dba_objects where rownum <=1000;
alter system flush shared_pool;
alter session set events '10053 trace name context forever, level 1';
select /*+use_nl(t1,t2)*/count(*) from test1 t1,test2 t2 where t1.object_id = t2.object_id;
alter session set events '10053 trace name context off';
trace的结果:
***************************************
OPTIMIZER STATISTICS AND COMPUTATIONS
***************************************
GENERAL PLANS
***************************************
Considering cardinality-based initial join order.
***********************
Join order[1]: TEST1[T1]#0 TEST2[T2]#1
***************
Now joining: TEST2[T2]#1
***************
NL Join
Outer table: Card: 100.00 Cost: 3.00 Resp: 3.00 Degree: 1 Bytes: 72
Inner table: TEST2 Alias: T2
Access Path: TableScan
NL Join: Cost: 311.61 Resp: 311.61 Degree: 0
Cost_io: 310.00 Cost_cpu: 49756767
Resp_io: 310.00 Resp_cpu: 49756767
Best NL cost: 311.61
resc: 311.61 resc_io: 310.00 resc_cpu: 49756767
resp: 311.61 resp_io: 310.00 resp_cpu: 49756767
Join Card: 100.00 = outer (100.00) * inner (1000.00) * sel (1.0000e-003)
Join Card - Rounded: 100 Computed: 100.00
Best:: JoinMethod: NestedLoop
Cost: 311.61 Degree: 1 Resp: 311.61 Card: 100.00 Bytes: 152
***********************
Best so far: Table#: 0 cost: 3.0024 card: 100.0000 bytes: 7200
Table#: 1 cost: 311.6068 card: 100.0000 bytes: 15200
***********************
Join order[2]: TEST2[T2]#1 TEST1[T1]#0
***************
Now joining: TEST1[T1]#0
***************
NL Join
Outer table: Card: 1000.00 Cost: 5.02 Resp: 5.02 Degree: 1 Bytes: 80
Inner table: TEST1 Alias: T1
Access Path: TableScan
NL Join: Cost: 1026.43 Resp: 1026.43 Degree: 0
Cost_io: 1024.00 Cost_cpu: 75104022
Resp_io: 1024.00 Resp_cpu: 75104022
Best NL cost: 1026.43
resc: 1026.43 resc_io: 1024.00 resc_cpu: 75104022
resp: 1026.43 resp_io: 1024.00 resp_cpu: 75104022
Join Card: 100.00 = outer (1000.00) * inner (100.00) * sel (1.0000e-003)
Join Card - Rounded: 100 Computed: 100.00
Join order aborted: cost > best plan cost
***********************
(newjo-stop-1) k:0, spcnt:0, perm:2, maxperm:2000
*********************************
Number of join permutations tried: 2
*********************************
(newjo-save) [1 0 ]
Final - All Rows Plan: Best join order: 1
Cost: 311.6068 Degree: 1 Card: 100.0000 Bytes: 15200
Resc: 311.6068 Resc_io: 310.0000 Resc_cpu: 49756767
Resp: 311.6068 Resp_io: 310.0000 Resc_cpu: 49756767
如果不加hint的话,oracle会对比两张表hash join,nested loop,merge join的cost,比较后选择最优,但用了hint后,只会出现nested loop的评估。所以说hint的原理就是给oracle加限制。
那到底用不用hint呢?短期来说Hint也许是个解决问题的最快方案,但它从长远来看会引入风险。无法保证以后数据分布情况不会变化;无法保证以后表结构不会变化,无法保证以后数据库不会升级。环境一直在变化,只有通过计算出各种执行计划的成本,选择最优的计划,才是最科学的。
结论是能不用就不用。