🙇‍♀️북마크 룩업

북마크 룩업

  • Index Scan이 항상 나쁜 것은 아니고
  • Index Seek가 항상 좋은것은 아니다
  • 인덱스를 활용하는데 어떻게 느릴 수가 있을까? => 북마크 룩업을 사용하기 때문

🪐차근차근

  • Heap Table[ {PAGE} {PAGE} ]

  • CLUSTERED의 경우 INDEX SEEK가 느릴 수가 없다
  • NonClustered의 경우, 데이터가 Leaf Page에 없다
  • 따라서 한번 더 타고 가야됨
    1. RID -> Heap Table (Bookbark Lookup)
    2. Key -> Clustered
SELECT *
INTO TestOrders
FROM Orders;

SELECT *
FROM TestOrders;

CREATE NONCLUSTERED INDEX Orders_Index01
ON TestOrders(CustomerID);
  • 인덱스 번호
SELECT Index_id, name
FROM sys.indexes
WHERE object_id = object_id('TestOrders');
  • 조회

DBCC IND('Northwind', 'TestOrders', 2);

9000
8960 8968 8969
Heap Table[ {PAGE} {PAGE} ]
  • 걸린 시간, 논리적 읽기 수, 실제 로직 경로 확인
SET STATISTICS TIME ON;
SET STATISTICS IO ON;
SET STATISTICS PROFILE ON;

🪐분석 시작

  • 기본 탐색을 해보자
SELECT *
FROM TestOrders
WHERE CustomerID = 'QUICK';
  • 강제로 인덱스를 이용하게 해보자
SELECT *
FROM TestOrders WITH INDEX(Orders_Index01)
WHERE CustomerID = 'QUICK';

논리적 읽기가 늘었음 => 항상 인덱스가 이득인 것은 아니다

🪐룩업을 줄이기 위한 몸부림

SELECT *
FROM TestOrders WITH INDEX(Orders_Index01)
WHERE CustomerID = 'QUICK' AND ShipVia = 3;

ROW가 28개인것을 알지만 ShipVia가 3인것은 모르므로 20개는 뻑이나고 8개만 살아남음

룩업을 줄여보자 경험에 따라 방법이 다 다른다!

복합인덱스를 활용

  • CORVERED INDEX
    • 모든 경우, 영역을 커버하겠다!
CREATE NONCLUSTERED INDEX Orders_Index01
ON TestOrders(CustomerID, ShipVia);

인덱스 SEEK가 8개만 찾는다

  1. 둘 다 만족하는것만 찾으니까 리프페이지 자체에서 판단가능
  2. Heap Table Lookup을 할 필요가 없다

Q) 그럼 조건1 AND 조건2 필요하면, 무조건 INDEX(조건1, 조건2)를 추가해주면 장떙? A) NO! 꼭 그렇지는 않다. DML(INSERT, UPDATE, DELETE) 작업 부하가 증가하게 된다

INCLUDE 활용

CREATE NONCLUSTERED INDEX Orders_Index01
ON TestOrders(CustomerID) INCLUDE (ShipVia);

키 값 자체는 CustomerID만 사용하기에 부담되지 않지만, 리프페이지에다가 ShipVia의 정보를 넣어는 것

데이터 순서에는 영향을 주지 않는다!

  • CLUSTERED INDEX 활용
    • 위와 같은 눈물겨운 노력에도 답이 없을 떄 사용
    • BU! CLUSTERED INDEX는 테이블당 1개만 사용 할 수 있다

🪐결론

NONCLUSTERED INDEX가 악영향을 주는 경우?

  • 북마크 룩업이 심각한 부하를 야기할 떄

대안은?

  1. Covered Index (검색할 모든 칼럼을 포함하겠다)
  2. Index에다가 Include로 힌트를 남긴다
  3. Clustered 고려 (단, 1번만 사용할 수 있는 궁극기..) -> NonClustered 악영향을 줄 수 있음

태그:

카테고리:

업데이트: