MS-SQL Server

넌클러스터드 인덱스의 SEEK 테스트

알 수 없는 사용자 2008. 4. 29. 13:57

 

CI(Clustered Index) NCI(Non-Clustered Index) 인덱스 상황에 따라 NCI Seek를 어떤식으로 하는지 테스트 해 보았습니다.

 

@@ 테스트 환경

OS : Windws XP Professional

SQL : Microsoft SQL Server 2005 - 9.00.3054.00 (Intel X86)

             Mar 23 2007 16:28:52

             Copyright (c) 1988-2005 Microsoft Corporation

             Developer Edition on Windows NT 5.1 (Build 2600: Service Pack 3)

 

 

--drop table idxTest

create table idxTest (

c1 int

, c2 int

, c3 int

, c4 int

)

 

-- 유니크 CI 한 개를만들고 넌클을1개 만든다.

create unique clustered index idx1 on idxTest (c1, c2)

create index idx3 on idxTest (c3, c4)

 

-- 테스트 데이터 입력

insert into idxTest select 1,1,1,1

insert into idxTest select 2,1,2,1

insert into idxTest select 3,1,3,1

insert into idxTest select 4,1,4,1

insert into idxTest select 5,1,5,1

insert into idxTest select 6,1,6,1

 

set statistics profile on

 

-- NCI 조건을 먼저 넣고, CI조건의 첫번째 컬럼을 넣어보자.

select * from idxTest

where c3=1 and c4=1 and c1=1

 

  |--Index Seek(OBJECT:([testDB].[dbo].[idxTest].[idx3]),

             SEEK:([testDB].[dbo].[idxTest].[c3]=CONVERT_IMPLICIT(int,[@1],0)

                           AND [testDB].[dbo].[idxTest].[c4]=CONVERT_IMPLICIT(int,[@2],0)

                           AND [testDB].[dbo].[idxTest].[c1]=CONVERT_IMPLICIT(int,[@3],0)) ORDERED FORWARD)

-- NCI 에서 NCI+CI모두를 가지고 seek 했다. ~ CI의 키가 NCI의 넌리프 레벨에 붙어 있는가보다.!

 

 

-- NCI 조건을 먼저 넣고, CI조건의 두번째 컬럼을 넣어보자.

select * from idxTest

where c3=1 and c4=1 and c2=1

 

  |--Index Seek(OBJECT:([testDB].[dbo].[idxTest].[idx3]),

             SEEK:([testDB].[dbo].[idxTest].[c3]=CONVERT_IMPLICIT(int,[@1],0)

                           AND [testDB].[dbo].[idxTest].[c4]=CONVERT_IMPLICIT(int,[@2],0)), 

             WHERE:([testDB].[dbo].[idxTest].[c2]=CONVERT_IMPLICIT(int,[@3],0)) ORDERED FORWARD)

-- CI 키가 NCI 키의 뒤에 순서대로 붙기 때문에 필터절로 빠진다.

 

 

-- CI의 유니크 상태에 따라 다른점이 있는지 확인해 보기 위해 CI에서 유니크를 빼고 다시 걸어 보았다.

drop index idxTest.idx1

create clustered index idx1 on idxTest (c1, c2)

 

 

-- NCI 조건을 먼저 넣고, CI조건의 첫번째 컬럼을 넣어보자.

select * from idxTest

where c3=1 and c4=1 and c1=1

 

  |--Index Seek(OBJECT:([testDB].[dbo].[idxTest].[idx3]),

             SEEK:([testDB].[dbo].[idxTest].[c3]=CONVERT_IMPLICIT(int,[@1],0)

                           AND [testDB].[dbo].[idxTest].[c4]=CONVERT_IMPLICIT(int,[@2],0)

                           AND [testDB].[dbo].[idxTest].[c1]=CONVERT_IMPLICIT(int,[@3],0)) ORDERED FORWARD)

-- 역시 NCI 에서 NCI+CI모두를 가지고 seek 했다. 무조건 CI의 키가 NCI의 넌리프에 붙어 있는건가?

 

 

 

-- NCI를 제거 후 유니크를 넣고 다시 걸어 보았다.

drop index idxTest.idx3

create unique index idx3 on idxTest (c3, c4)

 

 

-- 다시 NCI 조건을 먼저 넣고, CI조건의 첫번째 컬럼을 넣어보자.

select * from idxTest

where c3=1 and c4=1 and c1=1

 

  |--Index Seek(OBJECT:([testDB].[dbo].[idxTest].[idx3]),

             SEEK:([testDB].[dbo].[idxTest].[c3]=CONVERT_IMPLICIT(int,[@1],0)

                           AND [testDB].[dbo].[idxTest].[c4]=CONVERT_IMPLICIT(int,[@2],0)), 

             WHERE:([testDB].[dbo].[idxTest].[c1]=CONVERT_IMPLICIT(int,[@3],0)) ORDERED FORWARD)

-- 유니크 NCI로 생성하니 NCI의 넌리프에서 CI의 키가 빠진 것 같다.

-- 어차피 유니크니 데이터를 SEEK해서 내려가면 1개의 데이터밖에 없어서 그런 것 같다.

 

 

-- 다시 CI에 유니크를 추가해 보았다.

drop index idxTest.idx1

create unique clustered index idx1 on idxTest (c1, c2)

 

-- 다시 NCI 조건을 먼저 넣고, CI조건의 첫번째 컬럼을 넣어보자.

select * from idxTest

where c3=1 and c4=1 and c1=1

 

  |--Index Seek(OBJECT:([testDB].[dbo].[idxTest].[idx3]),

             SEEK:([testDB].[dbo].[idxTest].[c3]=CONVERT_IMPLICIT(int,[@1],0)

                           AND [testDB].[dbo].[idxTest].[c4]=CONVERT_IMPLICIT(int,[@2],0)), 

             WHERE:([testDB].[dbo].[idxTest].[c1]=CONVERT_IMPLICIT(int,[@3],0)) ORDERED FORWARD)

-- 역시 CI의 키에 대해서는 필터처리를 했다.

 

-- 결론!

NCI의 넌리프 레벨에 CI의 키가 붙을지 말지는 NCI의 유니크 상황에 따라 결정이 되는 것 같다.

NCI 가 유니크한 경우 : CI의 키가 NCI의 넌리프레벨에 포함되지 않는다.

NCI 가 유니크하지 않은 경우 : CI의 키가 NCI의 넌리프레벨에 포함된다.



넥슨 DB 팀 ( http://nexondbteam.tistory.com )
하만철 / Ha Man cheol