클러스터 인덱스는 정렬을 보장할 수 없다(?).
SCAN 방식에는 2가지 종류가 있다.
- Allocation Ordered Scan
이 스캔 방식은 IAM(index Allocation Map) 페이지를 통해서 혼합 익스텐트(Mixed Extent)를 읽고 난 후에
균일 익스텐트(Uniform Extent)를 순서대로 읽는 방식이다.
- Index Ordered Scan
인덱스 스캔 방식으로 인덱스의 Double Linked List 구조 기반으로 next page 포인터로 연결된 다음 페이지들을 읽는 방식이다.
이런 스캔 방식때문에 클러스터 인덱스가 있음에도 불구하고 정렬되지 않은 데이터를 가져올수있다.
CLUSTERED INDEX를 생성하면 데이터페이지가 CLUSTERED INDEX의 키 값으로 정렬이 되므로
SELECT * FROM 테이블명 할 경우 정렬이 된 결과 값이 출력되어야 하는데 그렇지 않은 경우가 있다.
[예제]
USE tempdb
GO
SET NOCOUNT ON;
CREATE TABLE dbo.t1 (c1 INT, c2 VARCHAR (8000));
GO
CREATE UNIQUE CLUSTERED INDEX ix
ON dbo.t1 (c1);
GO
-- 먼저 10~100 까지 INSERT 한 후 1~9 까지 INSERT를 한다.
DECLARE @a INT;
SELECT @a = 10;
WHILE (@a < 100)
BEGIN
INSERT INTO dbo.t1 VALUES (@a, replicate ('a', 5000))
SELECT @a = @a + 1
END;
SELECT @a = 1;
WHILE (@a < 10)
BEGIN
INSERT INTO dbo.t1 VALUES (@a, replicate ('a', 5000))
SELECT @a = @a + 1
END;
GO
SELECT * FROM dbo.t1;
SELECT * FROM dbo.t1 WITH (READUNCOMMITTED);
비교를 해보면 서로 다른 결과가 나온다.
정렬이 보장 되지 않는 경우는 3가지 조건이 있다.
- READUNCOMMITTED 이거나 읽기 전용 환경인 경우
- SQL SERVER 2005 이상에서 테이블 페이지가 64 이상인 경우
- 실행계획에 Ordered 연산자가 false (order by 가 없는 경우)
결론은 정렬이 필요한 경우 ORDER BY를 꼭 사용해야 한다!!.