ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 복합 인덱스 컬럼 순서
    데이터베이스 with MSSQL/SQL 튜닝 2022. 4. 15. 23:18

    1. 준비

    USE Northwind; 
    
    SELECT *
    INTO TestOrders
    From Orders;
    
    DECLARE @i INT = 1;
    DECLARE @emp INT;
    SELECT @emp = MAX(EmployeeID) FROM Employees;
    
    -- 더미 데이터를 늘리는 작업 ( 830 * 1000 )
    WHILE(@i < 1000)
    BEGIN
    	INSERT INTO TestOrders(CustomerID, EmployeeID, OrderDate)
    	SELECT CustomerID, @emp + @i, OrderDate
    	FROM Orders;
    	SET @i = @i + 1;
    END
    
    CREATE NONCLUSTERED INDEX idx_emp_ord
    ON TestOrders(EmployeeID, OrderDate);
    
    CREATE NONCLUSTERED INDEX idx_ord_emp
    ON TestOrders(OrderDate, EmployeeID);
    
    SET STATISTICS TIME ON;
    SET STATISTICS IO ON;

    테스트용 테이블을 생성하였고 순서에 따라 비교할 인덱스를 2개 생성하였다.

    그리고 충분한 비교가 되게 데이터의 크기를 1000배로 늘려주었다.

     

    2. 순서에 따른 비교

    CASE1) 단순하게 순서만 바꾸기

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

    idx_emp_ord : 논리적 읽기 5

    idx_ord_emp : 논리적 읽기 5

    결론, 단순값만 비교할 때는 순서에 구애받지 않는다.

     

    CASE2) WHERE조건을 범위로 설정하기

    SELECT *
    FROM TestOrders WITH(INDEX(idx_emp_ord))
    WHERE EmployeeID = 1 AND OrderDate BETWEEN '19970101' AND '19970103';
    -- OrderDate >= '19970101' AND OrderDate <= '19970103'같은 방법으로도 사용할 수 있음
    
    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

    차이가 발생하는 이유는 Index(a, b, c)로 구성되어 있을 때 선행에 between을 사용하면 후행은 인덱스 기능을 상실한다.
    예를들어, a에 between이 걸리면 b와 c의 인덱스기능이 상실되고, b에 between이 걸리면 c의 인덱스기능이 상실한다.

     

    CASE3) IN-LIST 활용

    SELECT *
    FROM TestOrders WITH(INDEX(idx_ord_emp))
    WHERE EmployeeID = 1 AND OrderDate IN ('19970101', '19970102', '19970103');
    
    SELECT *
    FROM TestOrders WITH(INDEX(idx_ord_emp))
    WHERE EmployeeID = 1 AND OrderDate IN ('19970101', '19970102', '19970103');

    idx_emp_ord : 논리적 읽기 11

    idx_ord_emp : 논리적 읽기 11

     

    경우에 따라선 between보다 좋을 수도 안좋을 수도 있다.

    between을 올바르게 사용하면 논리적 읽기가 5인 반면에 올바르게 사용하지 못하면 논리적 읽기가 16이 나오는데 IN-LIST를 활용할 때는 11로 동일하게 나온다.

    결론적으로, 선행에 BETWEEN이 불가피하게 오는 경우에만 IN-LIST를 활용하면 좋다.

     

    '데이터베이스 with MSSQL > SQL 튜닝' 카테고리의 다른 글

    Merge  (0) 2022.04.19
    Nested Loop 조인  (0) 2022.04.18
    북마크 룩업  (0) 2022.04.15
    Index Scan vs Index Seek  (0) 2022.04.14
    Clustered vs NonClustered  (0) 2022.04.13
Designed by Tistory.