이전 시간과 마찬가지로 Northwind Database를 사용한다.
📌 Northwind Database 다운로드 및 설정
🔗 Northwind GitHub Repository
✅ 현재 데이터베이스 정보 확인
-- 데이터베이스 정보 확인
EXEC sp_helpdb 'Northwind';
✅ Northwind의 테이블 목록 확인
SELECT * FROM sys.tables;
📌 복합 인덱스(Composite Index) 개념
(OrderID, ProductID)를 인덱스로 설정하면 두 컬럼을 동시에 검색할 때 유리 📌 복합 인덱스의 장점
✅ 다중 컬럼 검색 속도 향상
✅ 첫 번째 컬럼만 검색해도 인덱스 적용 가능
📌 복합 인덱스의 단점
❌ 두 번째 컬럼만 검색하면 인덱스가 무용지물
❌ 데이터 변경이 많으면 인덱스 유지 비용 증가
✅ 기존 데이터 복사
-- 주문 상세 정보 테이블을 복사하여 테스트용 테이블 생성
SELECT *
INTO TestOrderDetails
FROM [Order Details];
-- 데이터 확인
SELECT * FROM TestOrderDetails;
✅ OrderID + ProductID 복합 인덱스 생성
CREATE INDEX Index_TestOrderDetails
ON TestOrderDetails(OrderID, ProductID);
✅ 생성된 인덱스 확인
EXEC sp_helpindex 'TestOrderDetails';
🔹 출력 예시
Index_Name Index_Description
---------------------------------------------------
PK_TestOrderDetails clustered, unique, primary key
Index_TestOrderDetails nonclustered located on PRIMARY
✅ 테스트 1: (OrderID, ProductID) 조건 검색
SELECT * FROM TestOrderDetails
WHERE OrderID = 10248 AND ProductID = 11;
✅ 테스트 2: (ProductID, OrderID) 순서 변경
SELECT * FROM TestOrderDetails
WHERE ProductID = 11 AND OrderID = 10248;
✅ 테스트 3: OrderID만 검색
SELECT * FROM TestOrderDetails
WHERE OrderID = 10248;
✅ 테스트 4: ProductID만 검색
SELECT * FROM TestOrderDetails
WHERE ProductID = 11;
📌 실행 계획 분석
🔹 테스트 1~3: Index Seek → GOOD ✅
🔹 테스트 4: Index Scan → BAD ❌
✅ 실행 계획을 확인하면 인덱스가 어떻게 적용되는지 알 수 있다.
SET STATISTICS IO ON;
SELECT * FROM TestOrderDetails WHERE ProductID = 11;
SET STATISTICS IO OFF;
✅ 인덱스 구조 확인 (DBCC IND 사용)
DBCC IND('Northwind', 'TestOrderDetails', 2);
📌 트리 구조 예시
[ Root: 992 ]
/ \
[936] [960]
/ \ / \
[952] [960] [961] [970]
✅ 특정 페이지의 데이터 조회
DBCC PAGE('Northwind', 1, 936, 3);
🔹 출력 결과
📌 결론
✅ 복합 인덱스는 첫 번째 컬럼을 기준으로 정렬됨
✅ 첫 번째 컬럼(OrderID)을 포함한 검색은 인덱스를 사용
✅ 두 번째 컬럼(ProductID)만 검색하면 인덱스가 적용되지 않음
✅ 50개의 데이터 추가
DECLARE @i INT = 0;
WHILE @i < 50
BEGIN
INSERT INTO TestOrderDetails
VALUES (10248, 100 + @i, 10, 1, 0);
SET @i = @i +1;
END;
✅ 변경된 인덱스 정보 확인
DBCC IND('Northwind', 'TestOrderDetails', 2);
📌 트리 구조 변경
[ Root: 992 ]
/ \
[936] [960]
/ \ / \
[952] [993] [961] [970]
✅ 새로운 페이지(Page 993)가 추가됨
DBCC PAGE('Northwind', 1, 993, 3);
📌 결론
✅ 데이터 추가 시 페이지 분할(SPLIT) 발생
✅ 페이지가 가득 차면 새로운 페이지가 생성됨
✅ 인덱스 성능 유지 위해 페이지 크기(FILLFACTOR) 조정 필요
✅ 새로운 Employees 복사 테이블 생성
SELECT LastName
INTO TestEmployees
FROM Employees;
-- 인덱스 추가
CREATE INDEX Index_TestEmployees
ON TestEmployees(LastName);
✅ Substring 사용 (Index Scan) → BAD
SELECT * FROM TestEmployees
WHERE SUBSTRING(LastName, 1, 2) = 'Bu';
📌 실행 계획 분석
❌ Index Scan 발생 (비효율적)
📌 원인
SUBSTRING(LastName, 1, 2) → LastName을 변형하여 SQL이 인덱스를 활용할 수 없음 ✅ LIKE 사용 (Index Seek) → GOOD
SELECT * FROM TestEmployees
WHERE LastName LIKE 'Bu%';
📌 Index Seek 발생 (효율적!)
✅ SQL이 LIKE 'Bu%'를 인덱스 범위 검색으로 처리