문제
Oracle이 겹치는 데이터가있는 경우 조항 사이에서 다중 연락을할까요? 내 응용 프로그램에서 사용자는 동적 검색어를 만들 수 있으므로 겹치는 데이터가있을 수 있습니다. Oracle은 나에게 SQL을 최적화합니까, 아니면 SQL을 만들기 전에 계산해야합니까?
즉
xxtable에서 id (10 ~ 20 사이) 또는 (18 ~ 30)에서 ID를 선택하십시오.
"그대로"또는 변환 될 것인가 :
xxtable where id (10 ~ 30)에서 ID를 선택하십시오.
시간 내 줘서 고마워.
해결책
쿼리에 따라 Optimizer가 어떻게 처리 할 것인지에 따라 다릅니다. Autotrace를 사용하여 SQLPLUS로 테스트하고 술어 정보를 살펴볼 수 있습니다 (이것은 Oracle 버전 10.2.0.3에서 수행) :
SQL>set autot traceonly
SQL>
1 select l
2 from (SELECT l
3 FROM (SELECT LEVEL l
4 FROM dual CONNECT BY LEVEL < 20
5 )
6 )
7 where l between 5 and 10
8* or l between 7 and 15;
11 rows selected.
Elapsed: 00:00:00.21
Execution Plan
----------------------------------------------------------
Plan hash value: 2403765415
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 13 | 2 (0)| 00:00:01 |
|* 1 | VIEW | | 1 | 13 | 2 (0)| 00:00:01 |
|* 2 | CONNECT BY WITHOUT FILTERING| | | | | |
| 3 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("L">=5 AND "L"<=10 OR "L">=7 AND "L"<=15)
2 - filter(LEVEL<20)
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
0 consistent gets
0 physical reads
0 redo size
494 bytes sent via SQL*Net to client
403 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
11 rows processed
이 경우 최적화 기준에 의해 재 작성은 Where Criteria에서 수행하지 않지만 약간 변경하는 경우 :
SQL>
1 select l
2 from (SELECT l
3 FROM (SELECT LEVEL l
4 FROM dual CONNECT BY LEVEL < 20
5 )
6 )
7 where l between 5 and 10
8* or l between 7 and 10;
6 rows selected.
Elapsed: 00:00:00.20
Execution Plan
----------------------------------------------------------
Plan hash value: 2403765415
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 13 | 2 (0)| 00:00:01 |
|* 1 | VIEW | | 1 | 13 | 2 (0)| 00:00:01 |
|* 2 | CONNECT BY WITHOUT FILTERING| | | | | |
| 3 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("L"<=10 AND ("L">=5 OR "L">=7))
2 - filter(LEVEL<20)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
0 consistent gets
0 physical reads
0 redo size
388 bytes sent via SQL*Net to client
392 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
6 rows processed
이것에 대해 우리는 옵티마이저가 기준이 동일한 상한을 갖는 위치를 인식한다는 것을 알 수 있습니다. 따라서 Optimizer가 어떻게 다시 작성하는지에 대한 쿼리에 따라 다릅니다.
다른 팁
인덱스가있는 실제 테이블에 대해 시험을 실행할 때 어떤 일이 발생하는지 살펴볼 가치가 있습니다. 이 예제 테이블에는 통계가 포함 된 COL_3의 69,241 행과 비 유니 키 인덱스가 있습니다.
사례 1: yer clauses 사이에 두 개의 겹치는 두 가지
SQL> set autotrace traceonly exp
SQL>
SQL> select * from big_table
2 where col_3 between 0.8 and 1
3 or col_3 between 0.9 and 1.1
4 /
Execution Plan
----------------------------------------------------------
Plan hash value: 3993303771
-------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 14737 | 805K| 176 (1)| 00:00:03 |
|* 1 | TABLE ACCESS FULL| BIG_TABLE | 14737 | 805K| 176 (1)| 00:00:03 |
-------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("COL_3"<=1.1 AND "COL_3">=0.9 OR "COL_3"<=1 AND
"COL_3">=0.8)
SQL>
결과: 인덱스가 무시되고 전체 테이블 스캔이 계속됩니다.
Case 2: 절 사이의 조항은 상한을 공유합니다
SQL> select * from big_table
2 where col_3 between 0.8 and 1.1
3 or col_3 between 0.9 and 1.1
4 /
Execution Plan
----------------------------------------------------------
Plan hash value: 1461639892
-----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 7924 | 433K| 114 (0)| 00:00:02 |
| 1 | TABLE ACCESS BY INDEX ROWID| BIG_TABLE | 7924 | 433K| 114 (0)| 00:00:02 |
|* 2 | INDEX RANGE SCAN | BIG3_IDX | 7924 | | 17 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("COL_3"<=1.1)
filter("COL_3">=0.8 OR "COL_3">=0.9)
SQL>
결과: 인덱스는 상한에 사용되며 전체 테이블 스캔을 피합니다.
사례 3 : 절 사이의 조항은 하한을 공유합니다
SQL> select * from big_table
2 where col_3 between 0.8 and 1.1
3 or col_3 between 0.8 and 1.2
4 /
Execution Plan
----------------------------------------------------------
Plan hash value: 3993303771
-------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 15146 | 828K| 176 (1)| 00:00:03 |
|* 1 | TABLE ACCESS FULL| BIG_TABLE | 15146 | 828K| 176 (1)| 00:00:03 |
-------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(("COL_3"<=1.2 OR "COL_3"<=1.1) AND "COL_3">=0.8)
SQL>
결과: 인덱스가 무시되고 전체 테이블 스캔이 계속됩니다.
Case 4: 범위 사이의 두 가지는 단일 조항으로 병합됩니다.
SQL> select * from big_table
2 where col_3 between 0.8 and 1.1
3 /
Execution Plan
----------------------------------------------------------
Plan hash value: 1461639892
-----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 7924 | 433K| 114 (0)| 00:00:02 |
| 1 | TABLE ACCESS BY INDEX ROWID| BIG_TABLE | 7924 | 433K| 114 (0)| 00:00:02 |
|* 2 | INDEX RANGE SCAN | BIG3_IDX | 7924 | | 17 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("COL_3">=0.8 AND "COL_3"<=1.1)
SQL>
결과: 인덱스는 상부와 하한에 사용됩니다.
따라서 요약하면, 절 사이의 두 가지가 겹치고 열에 인덱스가 있으면 병합하려는 노력의 가치가있을 수 있습니다.