개요
Tibero에서는 WHERE 절 조건에 따라 인덱스를 활용한 UNIQUE SCAN이 수행되며, 이는 쿼리 성능에 큰 영향을 줍니다.
하지만 바인드 변수의 타입이 인덱스 컬럼의 타입과 일치하지 않는 경우, 기대한 UNIQUE SCAN이 수행되지 않고 전체 인덱스 탐색(Index Full Scan에 가까운 동작)으로 변경될 수 있습니다.
본 자료에서는 바인드 변수 타입에 따른 실행계획 차이를 실험하고, 실무에서의 대응 방안을 제시합니다.
방법
실험 환경 및 시나리오
실험 데이터 구성
DROP TABLE t; CREATE TABLE t ( c1 VARCHAR(20) UNIQUE );
INSERT INTO t VALUES ('001');
INSERT INTO t VALUES ('1.0');
INSERT INTO t VALUES ('1.00');
INSERT INTO t SELECT TO_CHAR(level) FROM dual CONNECT BY level < 1000000;
COMMIT;
SQL
복사
실험 시나리오 비교
시나리오 | 바인드 타입 | 조건 예시 | 반환 Row 수 | 예상 스캔 유형 |
A | NUMBER | :b := 1 | 최대 4건 | Index 범위 스캔 |
B | VARCHAR | :b := '1.0' | 1건 | Index Unique Scan |
실행계획 비교 및 성능분석
1. 시나리오 A_바인드 타입: NUMBER
VAR b NUMBER;
EXEC :b := 1;
SET AUTOT ON EXP STAT PLANS
SELECT * FROM t WHERE c1 = :b;
SQL
복사
Execution Plan
1 COLUMN PROJECTION (Cost:3, %%CPU:0, Rows:1)
2 INDEX (UNIQUE SCAN): _SYS_CON1105700182 (Cost:3, %%CPU:0, Rows:1)
SQL
복사
Execution Stat
1 COLUMN PROJECTION (Time:.03 ms, Rows:4, Starts:1)
2 INDEX (UNIQUE SCAN): _SYS_CON1105700182 (Time:437.43 ms, Rows:4, Starts:1)
SQL
복사
Predicate Information
2 - access: ("T"."C1" = :B) (0.000)
SQL
복사
기타 통계 정보
항목 | 값 |
db block gets | 147 |
consistent gets | 2,395 |
physical reads | 0 |
redo size | 0 |
sorts (disk) | 0 |
sorts (memory) | 6 |
rows processed | 4 |
2. 시나리오 B_바인드 타입: VARCHAR
VAR b varchar(10);
EXEC :b := '1.0';
SET AUTOT ON EXP STAT PLANS
SELECT * FROM t WHERE c1 = :b;
SQL
복사
Execution Plan
1 COLUMN PROJECTION (Cost:3, %%CPU:0, Rows:1)
2 INDEX (UNIQUE SCAN): _SYS_CON1105700182 (Cost:3, %%CPU:0, Rows:1)
SQL
복사
Execution Stat
1 COLUMN PROJECTION (Time:.01 ms, Rows:1, Starts:1)
2 INDEX (UNIQUE SCAN): _SYS_CON1105700182 (Time:.05 ms, Rows:1, Starts:1)
SQL
복사
Predicate Information
2 - access: ("T"."C1" = :B) (0.000)
SQL
복사
기타 통계 정보
항목 | 값 |
db block gets | 0 |
consistent gets | 15 |
physical reads | 0 |
redo size | 60 |
sorts (disk) | 0 |
sorts (memory) | 1 |
rows processed | 1 |
문제 발생 조건
아래의 조건 중 하나도 만족되지 않을 경우, 바인드 변수 타입으로 캐스팅이 발생하면서 UNIQUE SCAN의 본래 동작이 무력화되고 인덱스 전체 스캔에 가까운 동작으로 변경됩니다.
조건 번호 | 조건 설명 |
1 | 인덱스 키와 바인드 파라미터의 타입이 동일한 경우 |
2 | 인덱스 키와 바인드 파라미터가 string 타입인 경우 (char, varchar, long, clob, nchar, nvarchar, nclob) |
3 | 인덱스 키와 바인드 파라미터의 타입 우선순위가 키 타입인 경우 |
실무 대응 전략
전략 | 설명 |
타입 일치 유지 | 바인드 변수와 인덱스 컬럼 타입을 정확히 일치화 필요 |
명시적 캐스팅 지양 | TO_CHAR, TO_NUMBER 등의 사용은 인덱스 무력화 초래 가능 |
실행계획 점검 | 해당 case는 plan만으로 확인이 어려워 cr reads의 정상 상태여부 확인 필요 |
개발 표준화 | 바인드 변수 타입 일치를 위한 코딩 표준 수립 필요 |
정리
인덱스 효율성 비교
비교항목 (바인드타입) | 영향 |
컬럼 타입인 경우 | 정확한 unique scan, 성능 우수 |
컬럼 타입이 아닌 경우 | 캐스팅 후 복수 매칭 → 성능 저하 |
바인드 타입과 인덱스 매칭 흐름도
[ 컬럼 타입: VARCHAR ]
│
├── 바인드 타입: NUMBER (:b := 1)
│ ↓ 암묵적 캐스팅
│ ↓ 여러 문자열 매칭 ('001', '1', '1.0', '1.00')
│ ↓ 복수 Row 반환 → Index Full Scan 유사
│
└── 바인드 타입: VARCHAR (:b := '1.0')
↓ 타입 일치
↓ 정확한 값 일치 ('1.0')
↓ Index Unique Scan → 빠른 처리
Plain Text
복사