반응형

본 포스트는 Microsoft TechNet의 [논리 및 물리 연산자 참조]내용을 참고하여 정리한 내용이다.

※실행 계획 연산자 전체 보기

 

Bookmark Lookup 연산자는 책갈피(행 ID 또는 클러스터링 키)를 사용하여 테이블이나 클러스터형 인덱스에서 해당 행을 조회한다. Argument 열에는 테이블이나 클러스터형 인덱스에서 행을 조회할 때 사용하는 책갈피 레이블이 포함된다. Argument 열에는 행을 조회하는 테이블 또는 클러스터형 인덱스의 이름도 포함된다. WITH PREFETCH 절이 Argument 열에 나타나는 경우에 쿼리 프로세서에서는 테이블 또는 클러스터형 인덱스에서 책갈피를 조회할 때 비동기 사전 인출(미리 읽기)을 사용하는 것을 최적의 방법으로 결정하게 된다.

 

SQL Server 2005 이후 버전에서는 Bookmark Lookup이 사용되지 않는다. 대신 Clustered Index SeekRID Lookup이 책갈피 조회 기능을 제공하며,  SQL Server 2005 서비스 팩 2 이후에서는 Key Lookup 연산자도 이 기능을 제공한다.

 

그래프 실행 계획 아이콘 

 

 

[주인장의 말.말.말]

위의 내용은 BOL을 인용한 것으로 처음 접하는 사람에게는 이해하기 힘들 수 있을 것이다. 블로그 주인이 Bookmark Lookup을 부연 설명하자면, 내가 Select하고자 하는 컬럼이 인덱스에 없을 경우 넌클러스터드 인덱스의 키 값을 가지고 힙 페이지 (혹은 클러스터형 인덱스가 있는 테이블일 경우는 클러스터형 인덱스를) 뒤지는 것을 의미한다. 따라서 힙이나 클러스터형 인덱스를 찾아가는 과정의 추가적인 Page I/O가 발생하게 된다.

이는 마치 Oracle에서 인덱스 영역에 저장되어 있는 rowid를 가지고 데이터 블록을 엑세스하는 과정과 같다.

하지만 내가 Select하고자 하는 컬럼이 모두 인덱스에 있을 때, 즉 인덱스가 모두 커버할 수 있을 때 - 이를 유식한 말로 Covered Index라고 한다. - 는 Bookmark Lookup이 발생하지 않게 될 것이다. 이는 아래의 예에서 확인해 보도록 하자.

 

BookMark Lookup 연산자의 예 (이 테스트는 SQL Server 2000에서 이루어졌다)

먼저, 앞서 소개한 dbo.idxinfo_v 뷰를 조회하여 authors 테이블의 인덱스를 먼저 확인해 본다.

SELECT Owner, TableName, IndexName, ClusterType, UniqueType, IndexType, AllColName
  FROM dbo.idxinfo_v
 WHERE TableName = 'authors'
GO

 

조회 결과

Owner TableName IndexName ClusterType UniqueType IndexType AllColName
dbo authors UPKCL_auidind CLUSTERED PRIMARY KEY CONSTRAINT au_id
dbo authors aunmind NONCLUSTERED INDEX   au_lname, au_fname

 

이제 아래의 SQL을 실행해 보자. 실행 계획에서 Bookmark Lookup을 확인 할 수 있을 것이다.

USE pubs
GO

 

SET NOCOUNT ON
GO

 

SET SHOWPLAN_ALL ON
GO

 

SELECT *
 FROM authors AS a
WHERE au_lname LIKE 'St%'
ORDER BY a.au_lname DESC
GO

 

SET SHOWPLAN_ALL OFF
GO

 

텍스트 실행 계획

SttText

SELECT *   FROM authors AS a   WHERE au_lname LIKE 'St%'  ORDER BY a.au_lname DESC

    |--Bookmark Lookup(BOOKMARK:([Bmk1000]), OBJECT:([pubs].[dbo].[authors] AS [a]))

       |--Index Seek(OBJECT:([pubs].[dbo].[authors].[aunmind] AS [a]),

          SEEK:([a].[au_lname] >= 'Ss' AND [a].[au_lname] < 'Su'), 

          WHERE:(like([a].[au_lname], 'St%', NULL)) ORDERED BACKWARD)

 

그래픽 실행 계획


 

 

다음의 앞에서 언급한 Covered Index의 예이다.

위 SQL에서 달라진 것은 Select한 컬럼이 모두 인덱스에 있다는 점 뿐이다.

USE pubs
GO

 

SET NOCOUNT ON
GO

 

SET SHOWPLAN_ALL ON
GO

 

SELECT a.au_lname, a.au_lname
 FROM authors AS a
WHERE au_lname LIKE 'St%'
ORDER BY a.au_lname DESC
GO

 

SET SHOWPLAN_ALL OFF
GO

 

텍스트 실행 계획

SttText

SELECT a.au_lname, a.au_lname   FROM authors AS a   WHERE au_lname LIKE 'St%'  ORDER BY a.au_lname DESC

    |--Index Seek(OBJECT:([pubs].[dbo].[authors].[aunmind] AS [a]),

       SEEK:([a].[au_lname] >= 'Ss' AND [a].[au_lname] < 'Su'),

       WHERE:(like([a].[au_lname], 'St%', NULL)) ORDERED BACKWARD)

 

그래픽 실행 계획


 

반응형

+ Recent posts