MS SQL Server에서 열 또는 열 수에 대한 색인을 작성할 때 (버전 2005를 사용하고 있음) 각 열의 색인이 오름차순 또는 내림차순으로 지정되도록 지정할 수 있습니다. 이 선택이 왜 여기에 있는지 이해하는 데 어려움을 겪고 있습니다. 이진 정렬 기술을 사용하면 조회 속도가 빠르지 않습니까? 어떤 순서를 선택하면 어떤 차이가 있습니까?
MS SQL Server에서 열 또는 열 수에 대한 색인을 작성할 때 (버전 2005를 사용하고 있음) 각 열의 색인이 오름차순 또는 내림차순으로 지정되도록 지정할 수 있습니다. 이 선택이 왜 여기에 있는지 이해하는 데 어려움을 겪고 있습니다. 이진 정렬 기술을 사용하면 조회 속도가 빠르지 않습니까? 어떤 순서를 선택하면 어떤 차이가 있습니까?
답변:
이것은 복합 인덱스와 함께 사용될 때 주로 중요합니다.
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
임의의 테이블에서 를 구성하는 열 은 항상 해당 테이블에서 다른 인덱스의 후행 열입니다.
진정한 단일 열 인덱스의 경우 쿼리 최적화 프로그램의 관점과 거의 차이가 없습니다.
테이블 정의
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 %% )