Mssql을 사용하며 Index를 타지 않는 Query를 정리해 보자
도움 된 블로그!
1. where 컬럼의 가공, 함수, 연산, 형변환 금지
SELECT
[buy_id]
, [product_id]
, [create_date]
FROM
[dbo].[pmt_product_buy]
WHERE
CONVERT(DATE, [create_date]) < '2022-01-01'
해당 쿼리는 create_date 컬럼에 대한 Index를 타지 않는다.
convert 함수를 통하여 변형이 되었기 때문에 create_date와는 다른 컬럼이 된다.
개선 방법은
SELECT
[buy_id]
, [product_id]
, [create_date]
FROM
[dbo].[pmt_product_buy]
WHERE
[create_date] BETWEEN '2022-01-01' AND '2022-03-01'
다른 함수를 사용하여 데이터를 조회해야 한다.
2. Like 검색 시 문자열 앞에 % 사용 금지
SELECT
t1.*
FROM
[dbo].[pmt_product_info] t1
WHERE
[product_price] LIKE '%3%'
문자열 앞에 %가 붙게 될 경우 product_price 컬럼의 인덱스와는 무관하게 전체 풀스캔을 타게 된다.
부득이하게 대용량의 모든 테이블을 조회할 경우에는 차라리 where을 통하여 한번 데이터를 필터링한 후 조회를 하거나
카프카와 검색 엔진을 사용하여 조회하면 좋다.
3. Null 조건의 사용
SELECT
t1.*
FROM
[dbo].[pmt_product_info] t1
WHERE
[product_price] is null
where절에 null을 사용할 경우 인덱스와 무관하게 풀 스캔을 하게 된다.
4. not(부정문)을 사용할 경우
SELECT
t1.*
FROM
[dbo].[pmt_product_info] t1
WHERE
[product_price] != 3000
부정문을 사용할 경우 index를 타지 않는다.
한 값에 대한 부정이 아닌 범위를 지정하여 검색하는 게 좋다.
SELECT
t1.*
FROM
[dbo].[pmt_product_info] t1
WHERE
[product_price] < 3000 and [product_price] > 3000
5. in, or 연산
SELECT
t1.*
FROM
[dbo].[pmt_product_info] t1
WHERE
[product_price] in (3000, 1500, 1000)
in 조건을 사용할 경우 항상 인덱스를 타지 않는 것이 아니라 in 조건 안에 포함되는 데이터가 많을 경우 데이터베이스가 판단하여 테이블을 풀스캔을 한다고 한다..;;
이 부분은 매우 흥미로운 부분이었다.
or 조건의 사용은
SELECT
t1.*
FROM
[dbo].[pmt_product_info] t1
WHERE
([product_price] = 3000 or [product_price] = 1500 or [product_price] = 1000)
or의 경우 인덱스를 사용하지 못한다. 참이 하나라도 있으면 참이기 때문에 풀 스캔을 타게 된다.
2023.09.25 추가
DISTINCT가 낮은 경우 인덱스를 만드는게 아니라 전체에서 찾는게 더 빠르기 때문에 인덱스를 안만드는게 좋다.
(ex 사전을 열었는데 남성과 여성의 확률이 50%일 경우 굳이 찾을 필요가 없어서 전체 테이블을 스캔)
6. 복합인덱스일 경우의 인덱스 호출 순서
SELECT
[buy_id]
, [product_id]
, [create_date]
FROM
[dbo].[pmt_product_buy]
WHERE
[product_price] = 3000
and [create_date] BETWEEN '2022-01-01' AND '2022-03-01'
복합 인덱스의 경우 인덱스의 순서가 product_price, create_date일 경우 순서대로 조건을 걸어야 한다.
이 부분도 되게 흥미로웠다.
참고 : tothek님의 블로그
해당 블로그를 보면서 더 공부를 해야겠다.
7. 올바르지 않은 데이터 타입 조회
SELECT
[buy_id]
, [product_id]
, [create_date]
FROM
[dbo].[pmt_product_buy]
WHERE
[product_price] = '3000'
product_price 컬럼의 경우 Int 타입이다.
하지만 String 타입의 값을 넣어 조회를 할 경우 인덱스를 타지 않을 수 있다.
---
어떤 분야든 파고들면 끝이 없는 것 같다.
그래도 다행인 건 모르는 지식을 알아가는 게 재미있어서 다행이다.
부족한 부분을 채우기 위해 GPT에게 물어봐서 팩폭도 맞았다. https://integer-ji.tistory.com/404
'글또' 카테고리의 다른 글
kakao tech meet 후기, AI와 Chat GPT.. (0) | 2023.05.11 |
---|---|
로드 밸런싱(Load Balancing) (0) | 2023.05.10 |
chat gpt 활용 (0) | 2023.03.19 |
브런치먹기 (1) | 2023.02.05 |
글또 7기를 시작하며 (1) | 2022.05.12 |