문제

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>

결과: 인덱스는 상부와 하한에 사용됩니다.

따라서 요약하면, 절 사이의 두 가지가 겹치고 열에 인덱스가 있으면 병합하려는 노력의 가치가있을 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top