고유 한 인덱스 업데이트 및 통계 행 수정 카운터


14

다음 표, 고유 클러스터형 인덱스 및 통계가 제공됩니다.

CREATE TABLE dbo.Banana
(
    pk integer NOT NULL, 
    c1 char(1) NOT NULL, 
    c2 char(1) NOT NULL
);

CREATE UNIQUE CLUSTERED INDEX pk ON dbo.Banana (pk);

CREATE STATISTICS c1 ON dbo.Banana (c1);
CREATE STATISTICS c2 ON dbo.Banana (c2);

INSERT dbo.Banana 
    (pk, c1, c2) 
VALUES 
    (1, 'A', 'W'), 
    (2, 'B', 'X'), 
    (3, 'C', 'Y'), 
    (4, 'D', 'Z');

-- Populate statistics
UPDATE STATISTICS dbo.Banana;

데이터 예

통계 행 수정 카운터는 업데이트 전에 분명히 0을 표시합니다.

-- Show statistics modification counters
SELECT
    stats_name = S.[name], 
    DDSP.stats_id,
    DDSP.[rows],
    DDSP.modification_counter
FROM sys.stats AS S
CROSS APPLY sys.dm_db_stats_properties(S.object_id, S.stats_id) AS DDSP
WHERE
    S.[object_id] = OBJECT_ID(N'dbo.Banana', N'U');

제로 수정 카운터

모든 pk열에 대해 각 열 값을 하나씩 증가시킵니다 .

-- Increment pk in every row
UPDATE dbo.Banana 
SET pk += 1;

실행 계획을 사용합니다.

분할 정렬 축소 실행 계획

다음과 같은 통계 수정 카운터를 생성합니다.

업데이트 후 수정 카운터

질문

  1. Split, Sort 및 Collapse 연산자는 무엇을합니까?
  2. 왜 이렇게 pk통계이 수정을 보여 주지만, c1c25를 보여?

답변:


15

SQL Server는 둘 이상의 행에 영향을 미치거나 영향을 줄 수있는 업데이트의 일부로 고유 인덱스유지 관리 할 때 항상 연산자의 분할, 정렬 및 축소 조합을 사용합니다 .

문제의 예를 통해 업데이트를 존재하는 네 개의 행 각각에 대해 별도의 단일 행 업데이트로 작성할 수 있습니다.

-- Per row updates
UPDATE dbo.Banana SET pk = 2 WHERE pk = 1;
UPDATE dbo.Banana SET pk = 3 WHERE pk = 2;
UPDATE dbo.Banana SET pk = 4 WHERE pk = 3;
UPDATE dbo.Banana SET pk = 5 WHERE pk = 4;

문제는 첫 번째 문이 pk1에서 2로 바뀌고 이미 pk= 2 인 행이 있기 때문에 실패한다는 것입니다 . SQL Server 저장소 엔진은 단일 문 내에서도 모든 처리 단계에서 고유 인덱스를 고유하게 유지해야합니다. . 분할, 정렬 및 축소로 해결 된 문제입니다.

스플릿 스플릿

첫 번째 단계는 각 update 문을 delete와 insert로 나누는 것입니다.

DELETE dbo.Banana WHERE pk = 1;
INSERT dbo.Banana (pk, c1, c2) VALUES (2, 'A', 'W');

DELETE dbo.Banana WHERE pk = 2;
INSERT dbo.Banana (pk, c1, c2) VALUES (3, 'B', 'X');

DELETE dbo.Banana WHERE pk = 3;
INSERT dbo.Banana (pk, c1, c2) VALUES (4, 'C', 'Y');

DELETE dbo.Banana WHERE pk = 4;
INSERT dbo.Banana (pk, c1, c2) VALUES (5, 'D', 'Z');

Split 연산자는 액션 코드 열을 스트림에 추가합니다 (여기서는 Act1007로 표시됨).

분할 속성

조치 코드는 업데이트의 경우 1, 삭제의 경우 3, 삽입의 경우 4입니다.

종류 종류

위의 split 문은 여전히 ​​잘못된 임시 고유 키 위반을 생성하므로 다음 단계는 업데이트되는 고유 인덱스의 키 ( pk이 경우)와 작업 코드별로 명령문을 정렬하는 것 입니다. 이 예제에서 이는 단순히 동일한 키에서 삭제 (3)가 삽입 (4) 전에 순서화됨을 의미합니다. 결과 순서는 다음과 같습니다.

-- Sort (pk, action)
DELETE dbo.Banana WHERE pk = 1;
DELETE dbo.Banana WHERE pk = 2;
INSERT dbo.Banana (pk, c1, c2) VALUES (2, 'A', 'W');
DELETE dbo.Banana WHERE pk = 3;
INSERT dbo.Banana (pk, c1, c2) VALUES (3, 'B', 'X');
DELETE dbo.Banana WHERE pk = 4;
INSERT dbo.Banana (pk, c1, c2) VALUES (4, 'C', 'Y');
INSERT dbo.Banana (pk, c1, c2) VALUES (5, 'D', 'Z');

속성 정렬

무너짐 무너짐

이전 단계는 모든 경우에 허위 고유 위반을 방지하기에 충분합니다. 최적화로서, Collapse는 인접한 삭제와 동일한 키 값에 대한 삽입 업데이트에 결합합니다.

-- Collapse (pk)
DELETE dbo.Banana WHERE pk = 1;
UPDATE dbo.Banana SET c1 = 'A', c2 = 'W' WHERE pk = 2;
UPDATE dbo.Banana SET c1 = 'B', c2 = 'X' WHERE pk = 3;
UPDATE dbo.Banana SET c1 = 'C', c2 = 'Y' WHERE pk = 4;
INSERT dbo.Banana (pk, c1, c2) VALUES (5, 'D', 'Z');

pk값 2, 3 및 4에 대한 삭제 / 삽입 쌍이 업데이트로 결합되어 단일 삭제는 pk= 1이고 삽입은 pk= 5입니다.

접기 연산자는 키 열을 기준으로 행을 그룹화하고 축소 결과를 반영하도록 조치 코드를 업데이트합니다.

속성 축소

클러스터형 인덱스 업데이트 클러스터형 인덱스 업데이트

이 연산자는 업데이트로 표시되어 있지만 삽입, 업데이트 및 삭제할 수 있습니다. 행당 클러스터형 인덱스 업데이트가 수행하는 작업은 해당 행의 작업 코드 값에 따라 결정됩니다. 연산자에는이 작업 모드를 반영하기위한 Action 속성이 있습니다.

클러스터형 인덱스 업데이트 작업 속성


행 수정 카운터

위의 세 가지 업데이트 는 유지 관리되는 고유 인덱스 의 키를 수정하지 않습니다 . 실제로 인덱스 의 열에 대한 업데이트를 아닌 열 ( c1c2)의 업데이트 와 삭제 및 삽입으로 변환했습니다. 삭제 나 삽입으로 잘못된 고유 키 위반이 발생할 수 없습니다.

삽입 또는 삭제는 행의 모든 ​​단일 열에 영향을 미치므로 모든 열과 관련된 통계는 수정 카운터가 증가합니다. 업데이트의 경우 업데이트 된 열이 선행 열로 값이 변경되지 않은 경우에도 수정 카운터가 증가합니다.

따라서 통계 행 수정 카운터 pkc1및에 대한 2 개의 변경 사항 과 5의 변경 사항을 표시합니다 c2.

-- Collapse (pk)
DELETE dbo.Banana WHERE pk = 1;                         -- All columns modified
UPDATE dbo.Banana SET c1 = 'A', c2 = 'W' WHERE pk = 2;  -- c1 and c2 modified
UPDATE dbo.Banana SET c1 = 'B', c2 = 'X' WHERE pk = 3;  -- c1 and c2 modified
UPDATE dbo.Banana SET c1 = 'C', c2 = 'Y' WHERE pk = 4;  -- c1 and c2 modified
INSERT dbo.Banana (pk, c1, c2) VALUES (5, 'D', 'Z');    -- All columns modified

참고 : 기본 개체에 적용된 변경 사항 만 (힙 또는 클러스터형 인덱스)에 통계 행 수정 카운터에 영향을줍니다. 비 클러스터형 인덱스는 기본 개체에 대한 변경 내용을 반영하여 보조 구조입니다. 통계 행 수정 카운터에는 전혀 영향을 미치지 않습니다.

개체에 여러 개의 고유 인덱스가있는 경우 별도의 분할, 정렬, 축소 조합을 사용하여 각각에 대한 업데이트를 구성합니다. SQL Server는 Split 결과를 Eager Table Spool에 저장 한 다음 각 고유 인덱스에 대해 해당 세트를 재생합니다 (이는 고유 한 인덱스 키별 정렬 코드 + 작업 코드 및 축소).

통계 업데이트에 대한 영향

쿼리 최적화 프로그램에 통계 정보가 필요하고 기존 통계가 오래 되었거나 스키마 변경으로 인해 유효하지 않은 경우 자동 통계 업데이트 (사용 가능한 경우)가 발생합니다 . 기록 된 수정 수가 임계 값을 초과하면 통계가 오래된 것으로 간주됩니다.

Split / Sort / Collapse 배열은 결과가 다릅니다 은 예상 한 행 수정이 기록되게합니다. 이는 통계 업데이트가 다른 경우보다 조만간 트리거 될 수 있음을 의미합니다.

위의 예에서 키 열의 행 수정은 4 (영향을받는 각 테이블 행에 대해 하나씩) 또는 5 (축소에 의해 생성 된 각 삭제 / 업데이트 / 삽입에 대해)가 아니라 2 (순 변경)만큼 증가합니다.

또한 원래 쿼리에 의해 논리적으로 변경되지 않은 키가 아닌 열은 행 수정을 누적 하여 업데이트 된 테이블 행의 두 배 (각 삭제에 대해 하나씩, 각 삽입에 대해 하나씩)를 가질 수 있습니다 .


기록 된 변경 수는 이전 키 열 값과 새 키 열 값의 겹침 정도에 따라 달라집니다 (따라서 별도의 삭제 및 삽입이 축소 될 수있는 정도). 각 실행간에 테이블을 재설정하면 다음 쿼리는 서로 다른 겹침으로 행 수정 카운터에 미치는 영향을 보여줍니다.

UPDATE dbo.Banana SET pk = pk + 0; -- Full overlap

pk = pk + 0

UPDATE dbo.Banana SET pk = pk + 1;

pk = pk + 1

UPDATE dbo.Banana SET pk = pk + 2;

pk = pk + 2

UPDATE dbo.Banana SET pk = pk + 3;

pk = pk + 3

UPDATE dbo.Banana SET pk = pk + 4; -- No overlap

pk = pk + 4

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