본문 바로가기

Programming/DB관련

인덱스를 타지 않는 쿼리

인덱스 컬럼 절을 변형한 경우

- 수식이나 함수 등으로 인덱스 컬럼 절을 변형하였을 경우

- 반드시 함수나 수식을 사용해야 하는 경우에는 인덱스 컬럼 부분에 적용하지 말고, 여기에 대입되는 컬럼이나 상수부분에 적용해야 한다.

SELECT column_name FROM table_name WHERE TO_CHAR(column_name, 'YYYYMMDD') = '20130909';

> SELECT column_name FROM table_name WHERE column_name = TO_DATE('20130909', 'YYYYMMDD');


SELECT column_name FROM table_name WHERE column_name * 100 > 10000;

> SELECT column_name FROM table_name WHERE column_name = 10000 / 100


내부적으로 데이터 형 변환이 일어난 경우

- 서로 대입되는 항목끼리 데이터 타입이 다르면 내부적인 형 변환에 의해 컬럼이 함수를 사용한 효과를 나타낸다.

SELECT column_name FROM table_name WHERE column_name  = '20130909'; // DATE 타입의 column

SELECT column_name FROM table_name WHERE column_name = TO_DATE('20130909', 'YYYYMMDD');


SELECT column_name FROM table_name WHERE column_name  = 100; // 문자 타입의 column

SELECT column_name FROM table_name WHERE column_name = '100';


조건절에 NULL 또는 NOT NULL을 사용하는 경우

- 기본적으로 인덱스를 구성한 컬럼 값이 전부 NULL이라면 인덱스는 이런 값을 저장하지 않는다.

따라서 NULL인 값이 많지 않아 인덱스를 통해 엑세스를 하고자 한다면 데이터 생성 시 디폴트로 0과 같이 데이터를 만들어주는 것이 좋다. 반대로, 만약 NOT NULL이 분석 대상이라면 해당 컬럼을 NULL 허용 컬럼으로 두는 것이 좋다.

SELECT column_name FROM table_name WHERE column_name IS NULL;

SELECT column_name FROM table_name WHERE column_name IS NOT NULL;

SELECT column_name FROM table_name WHERE column_name > '';

SELECT column_name FROM table_name WHERE column_name >= 0;


부정형으로 조건을 사용한 경우

- 부정문은 인덱스를 활용하지 못한다.

SELECT column_name FROM table_name WHERE column_name != 30;

SELECT column_name FROM table_name WHERE column_name < 30 AND column_name > 30;


또는 테이블을 한 번 더 읽어 NOT EXISTS를 사용

SELECT column_name FROM table_name WHERE NOT EXISTS 

   (SELECT column_name FROM table_name WHERE column_name = 30);


LIKE 연산자를 사용하였을 경우

LIKE 연산자를 이용하여 검색을 할 경우 %를 앞에 넣어 사용하게 되면 인덱스를 타지 않는다.

SELECT column_name FROM table_name WHERE column_name LIKE '%S%';

SELECT column_name FROM table_name WHERE column_name LIKE 'S%';


가능하면 INSTR을 사용하는 것도 나쁘지 않다.

INSTR('비교할 대상', '비교하고자하는 값', 비교를 시작할 위치, 검색된 결과의 순번);

SELECT column_name  FROM table_name WHERE INSTR(column_name  , 'cmp_value') > 0; 


OR 조건 사용

SELECT column_name FROM table_name1 t1, table_name2 t2

WHERE (t1.column_name1 = t2.column_name1 OR t1.column_name2 = t2.column_name2)

AND t1.column_name3 = 'cmp_value';


SELECT column_name FROM table_name1 t1, table_name2 t2

WHERE t1.column_name1 = t2.column_name1 AND t1.column_name3 = 'cmp_value';

UNION ALL

SELECT column_name FROM table_name1 t1, table_name2 t2

WHERE t1.column_name2 = t2.column_name2 AND t1.column_name3 = 'cmp_value';


참고자료 : 

데브기어_문효섭_효율적인 SQL 작성을 위한 SQL 프로파일링 및 튜닝_110909.pdf

'Programming > DB관련' 카테고리의 다른 글

Oracle Data Dictionary (데이터 사전)  (0) 2014.09.03
INDEX (인덱스)  (0) 2013.09.10
SQL LOADER란?  (0) 2013.04.24
오라클 백업 및 복구 (Export/Import)  (1) 2013.04.24
DELETE, DROP, TRUNCATE의 비교  (0) 2013.04.24