홈 › 대용량·배치 › 04 / 8

통계 정보와 힌트

옵티마이저가 계획을 고르는 근거와 강제하는 법
섹션 6진행 0 / 8

4. 응용 변형 예제

예제 6: 힌트 주석은 H2 에서 무시된다

Oracle 힌트를 넣은 쿼리를 H2 로 실행하면 오류 없이 돌고 결과가 같습니다. 힌트가 효과를 냈다는 뜻이 아니라 H2 가 주석으로 취급했다는 뜻입니다.

sql
SELECT /*+ INDEX(o idx_orders_status) */ COUNT(*) AS cnt FROM orders o WHERE o.status = 'CANCEL';
text
CNT
---
50
(1행)

힌트를 뺀 같은 쿼리도 50 이었습니다. 힌트는 계획을 바꿀 뿐 결과를 바꾸지 않는 것이 원칙이라 결과는 같아야 합니다.

sql
SELECT /*+ INDEX(x no_such_index) */ COUNT(*) AS cnt FROM orders o WHERE o.status = 'CANCEL';
text
CNT
---
50
(1행)

별칭 x 도 없고 없는 인덱스 이름인데 오류가 나지 않았습니다. H2 는 힌트를 읽지 않기 때문입니다.

주의

실제 Oracle 도 힌트 문법이 틀리거나 별칭이 안 맞으면 오류 없이 힌트를 무시합니다. 힌트를 쓴 뒤에는 실행 계획으로 실제로 적용됐는지 확인해야 합니다. 힌트에서 표를 가리킬 때는 FROM 에 쓴 별칭을 씁니다.

예제 7: DB별 힌트 문법 (문법 검토만)

같은 뜻을 DB별로 쓰면 아래와 같습니다. 문법 검토만 한 것이며 실행하지 않았습니다.

sql
-- Oracle · Tibero
SELECT /*+ INDEX(o idx_orders_status) */
       COUNT(*)
  FROM orders o
 WHERE o.status = 'CANCEL';

SELECT /*+ FULL(o) */
       COUNT(*)
  FROM orders o
 WHERE o.status = 'DONE';
sql
-- MySQL
SELECT COUNT(*) FROM orders o FORCE INDEX (idx_orders_status) WHERE o.status = 'CANCEL';
SELECT COUNT(*) FROM orders o IGNORE INDEX (idx_orders_status) WHERE o.status = 'DONE';
sql
-- MSSQL
SELECT COUNT(*) FROM orders o WITH (INDEX(idx_orders_status)) WHERE o.status = 'CANCEL';
SELECT COUNT(*) FROM orders o WHERE o.status = 'DONE' OPTION (RECOMPILE);

Oracle 의 FULL(o) 는 전체 읽기 지시입니다. 95% 를 읽는 DONE 조회는 인덱스보다 전체 읽기가 낫습니다. MySQL 의 FORCE INDEX 는 전체 읽기보다 지정한 인덱스를 쓰라는 강한 지시이고, IGNORE INDEX 는 지정한 인덱스를 못 쓰게 합니다. MSSQL 의 OPTION (RECOMPILE) 은 실행마다 계획을 다시 세워 파라미터 스니핑을 피합니다.

예제 8: 통계를 고친 뒤의 계획 (도식, H2 미지원)

통계를 다시 모은 뒤 같은 쿼리의 계획은 실제 분포에 맞게 바뀝니다. 수집 명령은 2.4 절의 GATHER_TABLE_STATS 입니다.

도식(H2 미지원, 실행 결과 아님)

text
| Id | Operation          | Name   | E-Rows | A-Rows |
-------------------------------------------------------
|  0 | SELECT STATEMENT   |        |        |      1 |
|  1 |  SORT AGGREGATE    |        |      1 |      1 |
|* 2 |   TABLE ACCESS FULL| ORDERS |  20050 |  20050 |

E-Rows 와 A-Rows 가 같아졌고 계획은 전체 읽기입니다. 취소가 80% 인 상황에서는 이 계획이 맞습니다. 힌트로 인덱스를 강제했다면 데이터가 이렇게 바뀐 뒤에도 느린 계획이 계속됐을 것입니다.