SQL Server 필터 색인 을 이용 하여 검색 어의 성능 분석 을 향상 시 킵 니 다.

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 색인 이 문장의 성능 을 향상 시 키 는 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 많이 지 켜 주시 기 바 랍 니 다!

좋은 웹페이지 즐겨찾기