Oracle Internals
JulianDyke.com

Welcome

Seminars

Consultancy

Calendar

Presentations

Diagnostics

Internals

References

Acknowledgements

Parameter: always_semi_join

Description

always use this method for semi-join when possible

Supported Versions

This 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

Unsupported Versions

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

Syntax

_ALWAYS_SEMI_JOIN = OFF | CHOOSE | NESTED_LOOPS | MERGE | HASH

In Oracle 9.2 the default value is CHOOSE

Example

This 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