Following @Justin Cave's answer, here is a small test case showing that Oracle is executing an INDEX RANGE SCAN followed by an INLIST ITERATOR . > for the next filter predicate :
WHERE (key_part_1, key_part_2) IN ( ('B',1), ('C',2) )
Customization
SQL> CREATE TABLE t(key1 VARCHAR2(1), key2 NUMBER); Table created. SQL> SQL> INSERT INTO t VALUES('A', 1); 1 row created. SQL> INSERT INTO t VALUES('B', 1); 1 row created. SQL> INSERT INTO t VALUES('C', 2); 1 row created. SQL> INSERT INTO t VALUES('C', 3); 1 row created. SQL> SQL> COMMIT; Commit complete. SQL>
A composite index on key1 and key2 :
SQL> CREATE INDEX t_idx ON t(key1, key2); Index created. SQL>
Collect statistics:
SQL> EXEC DBMS_STATS.gather_table_stats('LALIT', 'T'); PL/SQL procedure successfully completed. SQL>
Run request:
SQL> SELECT * FROM t 2 WHERE (key1, key2) IN ( ('B',1), ('C',2) ); K KEY2 - ---------- B 1 C 2 SQL>
Thus, he gives the correct result.
See the explanation plan:
Case No. 1 A pair of value keys in the same index order. Leading key in front.
SQL> SELECT * FROM TABLE(dbms_xplan.display); PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- Plan hash value: 2301620486 --------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 2 | 10 | 1 (0)| 00:00:01 | | 1 | INLIST ITERATOR | | | | | | |* 2 | INDEX RANGE SCAN| T_IDX | 2 | 10 | 1 (0)| 00:00:01 | --------------------------------------------------------------------------- Predicate Information (identified by operation id): PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- --------------------------------------------------- 2 - access(("KEY1"='B' AND "KEY2"=1 OR "KEY1"='C' AND "KEY2"=2)) 14 rows selected.
Case No. 2 A pair of value keys in the opposite order of the index. Lead key in the opposite direction.
SQL> EXPLAIN PLAN FOR SELECT * FROM t 2 WHERE (key2, key1) IN ( (1, 'B'), (2, 'C') ); Explained. SQL> SQL> SELECT * FROM TABLE(dbms_xplan.display); PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- Plan hash value: 2301620486 --------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 2 | 10 | 1 (0)| 00:00:01 | | 1 | INLIST ITERATOR | | | | | | |* 2 | INDEX RANGE SCAN| T_IDX | 2 | 10 | 1 (0)| 00:00:01 | --------------------------------------------------------------------------- Predicate Information (identified by operation id): PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- --------------------------------------------------- 2 - access(("KEY1"='B' AND "KEY2"=1 OR "KEY1"='C' AND "KEY2"=2)) 14 rows selected.
In both cases, Oracle uses an index .