全部博文(323)
分类: Delphi
2009-04-03 14:43:26
This parameter specifies the join method for semi-joins. These types of joins are carried out by Optimizer after transforming a query. In such joins, duplicate values from the inner table are removed and then the type of join specified in the parameter is used to perform a semi-join. It can be set to NESTED_LOOPS, MERGE or HASH. In Oracle 8i, it is defaulted to STANDARD and in Oracle 9i it is defaulted to CHOOSE, to pick up an appropriate join. This parameter is renamed to _ALWAYS_SEMI_JOIN as of Oracle 9i.
原来这个参数是在9i的时候引进来的,之前叫always_semi_join。再来寻寻它的历史。
Parameter: always_semi_join Descriptionalways use this method for semi-join when possible
Supported VersionsThis supported parameter was introduced in Oracle 8.0.4
This supported parameter was removed in Oracle 9.0.1
Version | Parameter Name | Data Type | Session Modifiable | System Modifiable |
8.0.4 | always_semi_join | String | FALSE | FALSE |
8.0.5 | always_semi_join | String | FALSE | FALSE |
8.0.6 | always_semi_join | String | FALSE | FALSE |
8.1.5 | always_semi_join | String | FALSE | FALSE |
8.1.6 | always_semi_join | String | FALSE | FALSE |
8.1.7 | always_semi_join | String | TRUE | FALSE |
This unsupported parameter was introduced in Oracle 9.0.1
Version | Parameter Name | Data Type | Session Modifiable | System Modifiable |
9.0.1 | _always_semi_join | String | TRUE | FALSE |
9.2.0 | _always_semi_join | String | TRUE | FALSE |
10.1.0 | _always_semi_join | String | TRUE | IMMEDIATE |
10.2.0 | _always_semi_join | String | TRUE | IMMEDIATE |
11.1.0 | _always_semi_join | String | TRUE | IMMEDIATE |
_ALWAYS_SEMI_JOIN = OFF | CHOOSE | NESTED_LOOPS | MERGE | HASH
In Oracle 9.2 the default value is CHOOSE
ExampleThis example was developed on an Oracle 9.2 database using a 2048 byte block size.
The example requires the following table and index definitions
CREATE TABLE t1 (c1 NUMBER NOT NULL, c2 NUMBER); CREATE TABLE t2 (c1 NUMBER NOT NULL, c2 NUMBER); ANALYZE TABLE t1 COMPUTE STATISTICS; ANALYZE TABLE t2 COMPUTE STATISTICS;With the default value for _ALWAYS_ANTI_JOIN
ALTER SESSION SET "_always_semi_join" = CHOOSE;the statement SELECT c2 FROM t1 WHERE EXISTS ( SELECT NULL FROM t2 WHERE t2.c1 = t1.c1 );
generates the execution plan
0 SELECT STATEMENT Optimizer=CHOOSE 1 0 HASH JOIN (SEMI) 2 1 TABLE ACCESS (FULL) OF 'T1' 3 1 TABLE ACCESS (FULL) OF 'T2'With _ALWAYS_SEMI_JOIN set to HASH
ALTER SESSION SET "_always_semi_join" = HASH;the same statement generates the same execution plan 0 SELECT STATEMENT Optimizer=CHOOSE 1 0 HASH JOIN (SEMI) 2 1 TABLE ACCESS (FULL) OF 'T1' 3 1 TABLE ACCESS (FULL) OF 'T2'
With _ALWAYS_ANTI_JOIN set to NESTED_LOOPS
ALTER SESSION SET "_always_semi_join" = NESTED_LOOPS;the same statement generates the execution plan 0 SELECT STATEMENT Optimizer=CHOOSE 1 0 NESTED LOOPS (SEMI) 2 1 TABLE ACCESS (FULL) OF 'T1' 3 1 TABLE ACCESS (FULL) OF 'T2'
With _ALWAYS_ANTI_JOIN set to MERGE
ALTER SESSION SET "_always_semi_join" = MERGE;the same statement generates the execution plan 0 SELECT STATEMENT Optimizer=CHOOSE 1 0 MERGE JOIN (SEMI) 2 1 SORT (JOIN) 3 2 TABLE ACCESS (FULL) OF 'T1' 4 1 SORT (JOIN) 5 4 TABLE ACCESS (FULL) OF 'T2'
With _ALWAYS_ANTI_JOIN set to OFF
ALTER SESSION SET "_always_semi_join" = OFF;the same statement generates the execution plan 0 SELECT STATEMENT Optimizer=CHOOSE 1 0 HASH JOIN (SEMI) 2 1 TABLE ACCESS (FULL) OF 'T1' 3 1 TABLE ACCESS (FULL) OF 'T2'
Note that in Oracle 9.2 (at least) _ALWAYS_SEMI_JOIN = OFF appears to have no effect
既然这样,修改初始化参数设置_always_semi_join=off的用意何在呢?我们的数据库版本是9.2.0.7.0。看来真是个bug了。在metalink上查了一下没有找到_always_semi_join=off跟execute SQL with large IN() clause无法有效的使用索引有什么联系。不过在查询的过程中又有了新的收获。这是关于从8.1.X 升级到 9.X关于子查询问题的诊断和解决。
oracle9i默认subquery unnesting 是enabled的。你可以通过下列方法来disable subquery unnesting :
当从8i升级到9i后遇到关于子查询的性能问题,可以尝试用以下方法进行诊断: