1️⃣ 인덱스를 구성하는 컬럼 순서, 왜 중요할까?

예를 들어, Index(Level, Race)라는 인덱스를 구성했다고 하자. 이때 (56, Human)이라는 조건으로 검색한다고 가정해보자.

이런 경우 "56"이라는 Level은 여러 명이 존재할 수 있으므로, Leaf Page 탐색은 여전히 순차적으로 이루어질 수밖에 없다. 즉, 북마크 룩업을 줄였다 하더라도 인덱스 컬럼 순서에 따라 성능 차이는 존재한다.


2️⃣ 실습 준비: 더미 데이터로 실험 환경 구성

USE Northwind;

-- 테이블 복사
SELECT * INTO TestOrders FROM Orders;

-- 더미 데이터 대량 추가 (830 * 1000)
DECLARE @i INT = 1, @emp INT;
SELECT @emp = MAX(EmployeeID) FROM Orders;

WHILE (@i < 1000)
BEGIN
	INSERT INTO TestOrders(CustomerID, EmployeeID, OrderDate)
	SELECT CustomerID, @emp + @i, OrderDate FROM Orders;
	SET @i = @i + 1;
END

3️⃣ 인덱스 두 개 생성

-- (EmployeeID, OrderDate) 순서
CREATE NONCLUSTERED INDEX idx_emp_ord
ON TestOrders(EmployeeID, OrderDate);

-- (OrderDate, EmployeeID) 순서
CREATE NONCLUSTERED INDEX idx_ord_emp
ON TestOrders(OrderDate, EmployeeID);

4️⃣ CASE 분석

✅ CASE 1: 두 조건 모두 = 일 때

-- idx_emp_ord 사용
SELECT * FROM TestOrders WITH(INDEX(idx_emp_ord))
WHERE EmployeeID = 1 AND OrderDate = '19970101';

-- idx_ord_emp 사용
SELECT * FROM TestOrders WITH(INDEX(idx_ord_emp))
WHERE EmployeeID = 1 AND OrderDate = '19970101';

📌 결과: 논리적 읽기 수, 실행 계획 모두 동일

두 컬럼 모두 정확히 일치하는 값으로 조회하는 경우, 컬럼 순서에 관계없이 인덱스를 잘 활용할 수 있다.


✅ CASE 2: BETWEEN을 활용한 범위 검색

-- EmployeeID가 선행
SELECT * FROM TestOrders WITH(INDEX(idx_emp_ord))
WHERE EmployeeID = 1 AND OrderDate BETWEEN '19970101' AND '19970103';

-- OrderDate가 선행
SELECT * FROM TestOrders WITH(INDEX(idx_ord_emp))
WHERE EmployeeID = 1 AND OrderDate BETWEEN '19970101' AND '19970103';

📌 결과:

  • idx_emp_ord: 논리적 읽기 5
  • idx_ord_emp: 논리적 읽기 16

🎯 결론: BETWEEN이 선행 컬럼에 적용되면 후행 컬럼은 인덱스 기능을 상실한다. 즉, 선행 조건은 =, 후행 조건에 BETWEEN을 사용하는 것이 가장 효율적이다.


✅ CASE 3: IN-LIST 조건 사용

-- IN 조건으로 대체
SELECT * FROM TestOrders WITH(INDEX(idx_ord_emp))
WHERE EmployeeID = 1 AND OrderDate IN ('19970101', '19970102', '19970103');

📌 결과: 논리적 읽기 11

BETWEEN이 선행에 걸렸을 때보다 더 나은 성능 (논리적 읽기 16 → 11)

단, 아래와 같이 선행이 =일 경우는 오히려 BETWEEN이 더 유리함.

-- idx_emp_ord 기준으로는 BETWEEN이 더 효율적
SELECT * FROM TestOrders WITH(INDEX(idx_emp_ord))
WHERE EmployeeID = 1 AND OrderDate IN ('19970101', '19970102', '19970103');
-- 논리적 읽기: 11
-- → BETWEEN 사용 시 논리적 읽기: 5

profile
李家네_공부방

0개의 댓글