SQL Server 필터 색인 을 이용 하여 검색 어의 성능 분석 을 향상 시 킵 니 다.
안녕하세요,저 는 기술 만 이야기 하고 머리 를 자 르 지 않 는 토 니 선생님 입 니 다.
Microsoft SQL Server 필터 색인(필터 색인)은 특정 조건 을 충족 하 는 데이터 줄 을 기반 으로 색인 을 하 는 것 을 말한다.전체 표 색인(기본 생 성)에 비해 좋 은 선별 색인 을 디자인 하면 조회 성능 을 향상 시 키 고 색인 유지 비용 을 줄 이 며 색인 저장 비용 을 낮 출 수 있 습 니 다.Microsoft SQL Server 의 필터 색인 기능 을 소개 합 니 다.
필터 색인 을 만 들 기 전에,우 리 는 그것 의 적용 장면 을 알 아야 한다.
4.567917.특정한 필드 에서 소량의 관련 값 만 조회 해 야 할 때 값 의 부분 집합 에 대해 필터 색인 을 만 들 수 있 습 니 다.예 를 들 어 필드 의 값 이 대부분 NULL 이 고 조회 가 비 NULL 값 에서 만 선택 할 때 비 NULL 데이터 줄 에 선별 색인 을 만 들 수 있 습 니 다.이 를 통 해 얻 은 색인 은 같은 필드 에 정 의 된 전체 표 비 집합 색인 에 비해 전자 가 적 고 유지 비용 이 적 습 니 다4.567917.표 에 분류 데이터 줄 이 포함 되 어 있 을 때 한 가지 또는 여러 가지 유형의 데 이 터 를 위해 선별 색인 을 만 들 수 있 습 니 다.조회 범 위 를 표 의 특정 구역 으로 축소 함으로써 이 데이터 줄 에 대한 조회 성능 을 향상 시 킬 수 있다.또한 이 를 통 해 얻 은 색인 은 전체 표 의 비 집합 색인 에 비해 전자 가 더 작고 유지 비용 이 더 적다색인 을 만 들 때 WHERE 자 구 를 통 해 색인 이 필요 한 데이터 줄 을 지정 하여 필터 색인 을 만 들 수 있 습 니 다.예 를 들 어 다음 주문서 orders:
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
customer_id INTEGER,
status VARCHAR(10)
);
BEGIN
DECLARE @counter INT = 1
WHILE @counter <= 1000000
BEGIN
INSERT INTO orders
SELECT @counter, (rand() * 100000),
CASE
WHEN (rand() * 100)<1 THEN 'pending'
WHEN (rand() * 100)>99 THEN 'shipped'
ELSE 'completed'
END
SET @counter = @counter + 1
END
END;
주문서 에는 모두 100 만 개의 주문 이 있 는데,일반적으로 대부분의 주문 은 완성 상태 에 있다.일반적인 상황 에서 저 희 는 특정한 사용자 가 완성 하지 못 한 주문 서 를 조회 하고 추적 해 야 하기 때문에 사용자 번호 와 상 태 를 바탕 으로 하 는 일부 색인 을 만 들 수 있 습 니 다.
CREATE INDEX full_idx ON orders (customer_id, status);
그리고 우 리 는 다음 검색 어의 실행 계획 을 살 펴 본다.
SET STATISTICS PROFILE ON
SELECT *
FROM orders
WHERE customer_id = 5043
AND status != 'completed';
id |customer_id|status |
------+-----------+-------+
743436| 5043|pending|
947848| 5043|shipped|
Rows Executes StmtText StmtId NodeId Parent PhysicalOp LogicalOp Argument DefinedValues EstimateRows EstimateIO EstimateCPU AvgRowSize TotalSubtreeCost OutputList Warnings Type Parallel EstimateExecutions
2 1 SELECT * FROM [orders] WHERE [customer_id]=@1 AND [status]<>@2 1 1 0 NULL NULL NULL NULL 1.405213 NULL NULL NULL 0.003283546 NULL NULL SELECT 0 NULL
2 1 |--Index Seek(OBJECT:([hrdb].[dbo].[orders].[full_idx]), SEEK:([hrdb].[dbo].[orders].[customer_id]=(5043) AND [hrdb].[dbo].[orders].[status] < 'completed' OR [hrdb].[dbo].[orders].[customer_id]=(5043) AND [hrdb].[dbo].[orders].[status] > 'completed') ORDERED FORWARD) 1 2 1 Index Seek Index Seek OBJECT:([hrdb].[dbo].[orders].[full_idx]), SEEK:([hrdb].[dbo].[orders].[customer_id]=(5043) AND [hrdb].[dbo].[orders].[status] < 'completed' OR [hrdb].[dbo].[orders].[customer_id]=(5043) AND [hrdb].[dbo].[orders].[status] > 'completed') ORDERED FORWARD [hrdb].[dbo].[orders].[id], [hrdb].[dbo].[orders].[customer_id], [hrdb].[dbo].[orders].[status] 1.405213 0.003125 0.0001585457 27 0.003283546 [hrdb].[dbo].[orders].[id], [hrdb].[dbo].[orders].[customer_id], [hrdb].[dbo].[orders].[status] NULL PLAN_ROW 0 1
출력 결과 검색 이용 색인 fullidx 스 캔 에 필요 한 데 이 터 를 찾 습 니 다.색인 full 를 볼 수 있 습 니 다.idx 가 사용 하 는 공간 크기:
SELECT ix.name AS "Index name",
SUM(sz.used_page_count) * 8/1024.0 AS "Index size (MB)"
FROM sys.dm_db_partition_stats AS sz
INNER JOIN sys.indexes AS ix ON sz.object_id = ix.object_id
AND sz.index_id = ix.index_id
INNER JOIN sys.tables tn ON tn.OBJECT_ID = ix.object_id
WHERE tn.name = 'orders'
GROUP BY ix.name;
Index name |Index size (MB)|
----------------------------+---------------+
full_idx | 26.171875|
PK__orders__3213E83F1E3B8A3B| 29.062500|
다음 에 우 리 는 일부 색인 을 만 들 고 완성 되 지 않 은 주문 데이터 만 포함 하여 색인 의 데 이 터 를 줄 입 니 다.
CREATE INDEX partial_idx ON orders (customer_id)
WHERE status != 'completed';
색인 partialidx 중 customer 만id 필드,status 필드 가 필요 없습니다.색인 partialidx 가 사용 하 는 공간 크기:
SELECT ix.name AS "Index name",
SUM(sz.used_page_count) * 8/1024.0 AS "Index size (MB)"
FROM sys.dm_db_partition_stats AS sz
INNER JOIN sys.indexes AS ix ON sz.object_id = ix.object_id
AND sz.index_id = ix.index_id
INNER JOIN sys.tables tn ON tn.OBJECT_ID = ix.object_id
WHERE tn.name = 'orders'
GROUP BY ix.name;
Index name |Index size (MB)|
----------------------------+---------------+
full_idx | 26.171875|
partial_idx | 0.289062|
PK__orders__3213E83F1E3B8A3B| 29.062500|
색인 은 26MB 가 아 닌 0.29MB 에 불과 합 니 다.대부분의 주문 이 완 료 된 상태 이기 때 문 입 니 다.다음 검색 은 필터 색인 을 적용 할 때의 실행 계획 을 보 여 줍 니 다.
SELECT *
FROM orders WITH ( INDEX ( partial_idx ) )
WHERE customer_id = 5043
AND status != 'completed';
Rows Executes StmtText StmtId NodeId Parent PhysicalOp LogicalOp Argument DefinedValues EstimateRows EstimateIO EstimateCPU AvgRowSize TotalSubtreeCost OutputList Warnings Type Parallel EstimateExecutions
2 1 SELECT * FROM orders WITH ( INDEX ( partial_idx ) ) WHERE customer_id = 5043 AND status != 'completed' 1 1 0 NULL NULL NULL NULL 1.124088 NULL NULL NULL 0.03279812 NULL NULL SELECT 0 NULL
2 1 |--Nested Loops(Inner Join, OUTER REFERENCES:([hrdb].[dbo].[orders].[id])) 1 2 1 Nested Loops Inner Join OUTER REFERENCES:([hrdb].[dbo].[orders].[id]) NULL 1.124088 0 4.15295E-05 24 0.03279812 [hrdb].[dbo].[orders].[id], [hrdb].[dbo].[orders].[customer_id], [hrdb].[dbo].[orders].[status] NULL PLAN_ROW 0 1
2 1 |--Index Seek(OBJECT:([hrdb].[dbo].[orders].[partial_idx]), SEEK:([hrdb].[dbo].[orders].[customer_id]=(5043)) ORDERED FORWARD) 1 3 2 Index Seek Index Seek OBJECT:([hrdb].[dbo].[orders].[partial_idx]), SEEK:([hrdb].[dbo].[orders].[customer_id]=(5043)) ORDERED FORWARD, FORCEDINDEX [hrdb].[dbo].[orders].[id], [hrdb].[dbo].[orders].[customer_id] 9.935287 0.003125 0.0001679288 15 0.003292929 [hrdb].[dbo].[orders].[id], [hrdb].[dbo].[orders].[customer_id] NULL PLAN_ROW 0 1
2 2 |--Clustered Index Seek(OBJECT:([hrdb].[dbo].[orders].[PK__orders__3213E83F1E3B8A3B]), SEEK:([hrdb].[dbo].[orders].[id]=[hrdb].[dbo].[orders].[id]) LOOKUP ORDERED FORWARD) 1 5 2 Clustered Index Seek Clustered Index Seek OBJECT:([hrdb].[dbo].[orders].[PK__orders__3213E83F1E3B8A3B]), SEEK:([hrdb].[dbo].[orders].[id]=[hrdb].[dbo].[orders].[id]) LOOKUP ORDERED FORWARD, FORCEDINDEX [hrdb].[dbo].[orders].[status] 1 0.003125 0.0001581 16 0.02946366 [hrdb].[dbo].[orders].[status] NULL PLAN_ROW 0 9.935287
우 리 는 fullidx 와 parialidx 에서 다음 조 회 를 실행 하 는 시간:
-- 300 ms
SELECT count(*)
FROM orders WITH ( INDEX ( full_idx ) )
WHERE status != 'completed';
-- 10 ms
SELECT count(*)
FROM orders WITH ( INDEX ( partial_idx ) )
WHERE status != 'completed';
또 필터 색인 은 다른 기능 을 실현 하 는 데 도 사용 된다.예 를 들 어,우 리 는 색인 parialidx 는 유일한 색인 으로 정의 되 어 모든 사용자 에 게 완료 되 지 않 은 주문 의 제약 만 존재 할 수 있 습 니 다.
DROP INDEX partial_idx ON orders;
TRUNCATE TABLE orders;
CREATE UNIQUE INDEX partial_idx ON orders (customer_id)
WHERE status != 'completed';
INSERT INTO orders(id, customer_id, status) VALUES (1, 1, 'pending');
INSERT INTO orders(id, customer_id, status) VALUES (2, 1, 'pending');
SQL [2601] [23000]: “partial_idx” “dbo.orders” 。 (1)。
사용 자 는 반드시 주문 서 를 완성 한 후에 야 새로운 주문 서 를 계속 생 성 할 수 있다.상기 소 개 를 통 해 알 수 있 듯 이 필터 색인 은 최 적 화 된 비 집합 색인 으로 특히 특정한 데이터 서브 에서 데 이 터 를 집중 적 으로 선택 하 는 조회 에 적합 하 다.
SQL Server 필터 색인 을 이용 하여 검색 어의 성능 을 향상 시 키 는 분석 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 관련 SQL Server 색인 이 문장의 성능 을 향상 시 키 는 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 많이 지 켜 주시 기 바 랍 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Redash를 사용할 때 몰랐던 SQL을 쓰는 법을 배웠습니다.최근 redash에서 sql을 쓸 기회가 많고, 이런 쓰는 방법이 있었는지와 sql에 대해 공부를 다시하고 있기 때문에 배운 것을 여기에 씁니다. Redash란? 월별로 데이터를 표시하고 싶습니다 주별로 데이터를 표...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.