SQL Server 인덱스-오름차순 또는 내림차순으로 어떤 차이가 있습니까?


138

MS SQL Server에서 열 또는 열 수에 대한 색인을 작성할 때 (버전 2005를 사용하고 있음) 각 열의 색인이 오름차순 또는 내림차순으로 지정되도록 지정할 수 있습니다. 이 선택이 왜 여기에 있는지 이해하는 데 어려움을 겪고 있습니다. 이진 정렬 기술을 사용하면 조회 속도가 빠르지 않습니까? 어떤 순서를 선택하면 어떤 차이가 있습니까?


답변:


136

이것은 복합 인덱스와 함께 사용될 때 주로 중요합니다.

CREATE INDEX ix_index ON mytable (col1, col2 DESC);

다음 중 하나에 사용할 수 있습니다.

SELECT  *
FROM    mytable
ORDER BY
        col1, col2 DESC

또는:

SELECT  *
FROM    mytable
ORDER BY
        col1 DESC, col2

그러나

SELECT  *
FROM    mytable
ORDER BY
        col1, col2

단일 열의 인덱스는 두 가지 방법으로 정렬하는 데 효율적으로 사용될 수 있습니다.

자세한 내용은 내 블로그의 기사를 참조하십시오.

최신 정보:

실제로 이것은 단일 열 인덱스의 경우에도 중요 할 수 있지만 그렇게 명확하지는 않습니다.

클러스터 된 테이블의 열에 대한 인덱스를 상상해보십시오.

CREATE TABLE mytable (
       pk INT NOT NULL PRIMARY KEY,
       col1 INT NOT NULL
)
CREATE INDEX ix_mytable_col1 ON mytable (col1)

인덱스는 col1정렬 된 값 col1과 행 참조를 유지합니다.

테이블이 클러스터되어 있으므로 행에 대한 참조는 실제로의 값입니다 pk. 또한의 각 값 내에서 주문됩니다 col1.

즉, 인덱스의 잎은 실제로 on으로 정렬되며이 (col1, pk)쿼리는 다음과 같습니다.

SELECT  col1, pk
FROM    mytable
ORDER BY
        col1, pk

정렬이 필요 없습니다.

다음과 같이 인덱스를 생성하면

CREATE INDEX ix_mytable_col1_desc ON mytable (col1 DESC)

그런 다음의 값은 col1내림차순으로 정렬되지만 pk각 값 내의 값은 col1오름차순으로 정렬됩니다.

이것은 다음 쿼리를 의미합니다.

SELECT  col1, pk
FROM    mytable
ORDER BY
        col1, pk DESC

에 의해 제공 될 수 ix_mytable_col1_desc있지만에 의해 제공 될 수는 없습니다 ix_mytable_col1.

다시 말해, CLUSTERED INDEX임의의 테이블에서 를 구성하는 열 은 항상 해당 테이블에서 다른 인덱스의 후행 열입니다.


1
"not for ..."라고 말하면 작동하지 않거나 성능이 끔찍할 것입니까?
Neil N

5
인덱스가 쿼리에 사용되지 않음을 의미합니다. 물론 쿼리 자체는 작동하지만 성능은 떨어집니다.
Quassnoi

1
첫 번째 섹션에서 두 번째 예는 "ORDER BY col1 DESC, col2 DESC"라고 말하면 안됩니까?
Mitch Wheat

71

진정한 단일 열 인덱스의 경우 쿼리 최적화 프로그램의 관점과 거의 차이가 없습니다.

테이블 정의

CREATE TABLE T1( [ID] [int] IDENTITY NOT NULL,
                 [Filler] [char](8000) NULL,
                 PRIMARY KEY CLUSTERED ([ID] ASC))

쿼리

SELECT TOP 10 *
FROM T1
ORDER BY ID DESC

BACKWARD실행 계획에서 볼 수있는 것처럼 스캔 방향 으로 정렬 된 스캔을 사용합니다 . 그러나 현재 FORWARD스캔 만 병렬 처리 할 수 ​​있다는 점에서 약간의 차이 가 있습니다.

계획

그러나 논리적 조각화 측면에서 큰 차이를 만들 수 있습니다 . 키가 내림차순으로 색인이 작성되지만 새 행에 오름차순 키 값이 추가되면 모든 페이지가 논리적 순서를 벗어나게됩니다. 이는 테이블을 스캔 할 때 IO 읽기 크기에 심각한 영향을 줄 수 있으며 캐시에 없습니다.

조각화 결과보기

                    avg_fragmentation                    avg_fragment
name   page_count   _in_percent         fragment_count   _size_in_pages
------ ------------ ------------------- ---------------- ---------------
T1     1000         0.4                 5                200
T2     1000         99.9                1000             1

아래 스크립트

/*Uses T1 definition from above*/
SET NOCOUNT ON;

CREATE TABLE T2( [ID] [int] IDENTITY NOT NULL,
                 [Filler] [char](8000) NULL,
                 PRIMARY KEY CLUSTERED ([ID] DESC))

BEGIN TRAN

GO
INSERT INTO T1 DEFAULT VALUES
GO 1000
INSERT INTO T2 DEFAULT VALUES
GO 1000

COMMIT

SELECT object_name(object_id) AS name, 
       page_count, 
       avg_fragmentation_in_percent, 
       fragment_count, 
       avg_fragment_size_in_pages 
FROM 
sys.dm_db_index_physical_stats(db_id(), object_id('T1'), 1, NULL, 'DETAILED') 
WHERE  index_level = 0 
UNION ALL 
SELECT object_name(object_id) AS name, 
       page_count, 
       avg_fragmentation_in_percent, 
       fragment_count, 
       avg_fragment_size_in_pages 
FROM 
sys.dm_db_index_physical_stats(db_id(), object_id('T2'), 1, NULL, 'DETAILED') 
WHERE  index_level = 0 

공간 결과 탭을 사용하여 후자의 페이지가 두 경우 모두 오름차순 키 값을 가지고 있기 때문이라고 가정 할 수 있습니다.

SELECT page_id,
       [ID],
       geometry::Point(page_id, [ID], 0).STBuffer(4)
FROM   T1
       CROSS APPLY sys.fn_PhysLocCracker( %% physloc %% )
UNION ALL
SELECT page_id,
       [ID],
       geometry::Point(page_id, [ID], 0).STBuffer(4)
FROM   T2
       CROSS APPLY sys.fn_PhysLocCracker( %% physloc %% )

여기에 이미지 설명을 입력하십시오


이 훌륭한 팁에 대해 Martin에게 감사합니다. 이것은 순위 쿼리에 정말 도움이되었습니다.
TheGameiswar

내림차순 인덱스가 있는지 궁금한 경우 \ @myvalue가 가능한 최소값에 가까워 졌을 때보 다 \ @myvalue가 가능한 최대 값에 가까울 때 indexed_column = \ @myvalue가 더 빠른 mytable에서 mycolumn을 선택하십시오.
Lajos Arpad

@LajosArpad 왜 더 빠를까요? B 나무는 균형 잡힌 나무입니다. 나무의 깊이는 둘 다 동일합니다.
Martin Smith

@MartinSmith 깊이는 동일하지만 형제의 순서가 차이를 만들지 않을 것입니다.
Lajos Arpad

@MartinSmith, 형제의 순서가 성능에 약간의 차이가있는 경우 다차원 조인은 말할 것도없이 수백만 개의 선택을 실행하면 추가됩니다.
Lajos Arpad

8

정렬 순서는 개별 레코드가 아닌 많은 정렬 된 데이터를 검색하려는 경우에 중요합니다.

(질문과 함께 제안하는 것처럼) 정렬 순서는 일반적으로 색인을 생성하는 열보다 훨씬 덜 중요합니다 (순서가 원하는 것과 반대이면 시스템이 색인을 반대로 읽을 수 있음). 나는 인덱스 정렬 순서를 거의 생각하지 않지만 인덱스가 포함 된 열에 대해 고민합니다.

@Quassnoi이 제공하는 좋은 예 는 때의 않습니다 중요합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.