재 색인이 통계를 업데이트합니까?


43

지난주에 MS10775A 과정을 해왔으며 트레이너가 신뢰할 수있는 대답을 할 수 없었던 한 가지 질문은 다음과 같습니다.

재 색인이 통계를 업데이트합니까?

우리는 온라인과 그렇지 않은 토론을 온라인에서 발견했습니다.


그것은 그 노트에 유용 REINDEX인덱스를 재 구축의 부작용으로 업데이트 열 통계를 않습니다 - 당신이하지 않는 필요한 통계를 업데이트 할 수 있습니다. 테이블의 데이터는 변경되지 않습니다. 동일한 데이터이며, a) 회전 플래터에서 페이지를 이동했을 때 (페이지가 재구성 될 때) 또는 b) 다른 페이지 (재 빌드의 경우)에 앉아있을뿐입니다. 따라서 색인 재 작성 (일부) 통계를 업데이트 하므로 수행 할 필요 가 없습니다.
Ian Boyd

답변:


51

통계 업데이트 ( 인덱스 재 구축 및 통계 업데이트 (벤자민 네 바레즈) 에서 복사)에 관심이있을 때 다음 사항을 명심할 수 있습니다.

  1. 기본적으로 UPDATE STATISTICS명령문은 테이블의 레코드 샘플 만 사용합니다. 를 사용 UPDATE STATISTICS WITH FULLSCAN하면 전체 테이블을 스캔합니다.

  2. 기본적 UPDATE STATISTICS으로이 명령문은 인덱스 및 열 통계를 모두 업데이트합니다. 이 COLUMNS옵션을 사용하면 열 통계 만 업데이트됩니다. 이 INDEX옵션을 사용하면 인덱스 통계 만 업데이트됩니다.

  3. 예를 사용하여 인덱스를 다시 작성 하면 테이블이 분할 되지 않은 경우ALTER INDEX … REBUILD 를 사용하는 것과 동등한 인덱스 통계가 업데이트 됩니다.이 경우 통계 만 샘플링 됩니다 (SQL Server 2012 이상에 적용됨).WITH FULLSCAN

  4. 를 사용하여 수동으로 작성된 통계는를 포함한 CREATE STATISTICS모든 ALTER INDEX ... REBUILD조작으로 업데이트되지 않습니다 ALTER TABLE ... REBUILD. ALTER TABLE ... REBUILD재 구축중인 테이블에 클러스터 된 인덱스가 정의 된 경우 클러스터형 인덱스에 대한 통계를 업데이트합니다.

  5. 예를 들어을 사용하여 인덱스를 재구성하면ALTER INDEX … REORGANIZE 통계가 업데이트되지 않습니다.

짧은 대답은 UPDATE STATISTICS열 통계를 업데이트하는 데 사용해야 하며 인덱스 재 구축은 인덱스 통계 만 업데이트한다는 것입니다. UPDATE STATISTICS (tablename) WITH FULLSCAN;구문을 사용 하여 인덱스 통계 및 수동으로 생성 된 통계를 포함하여 테이블의 모든 통계를 강제로 업데이트 할 수 있습니다 .

다음 코드는 위에 캡슐화 된 규칙을 보여줍니다.

먼저 몇 개의 열과 클러스터 된 인덱스가있는 테이블을 만듭니다.

USE tempdb;

IF OBJECT_ID(N'dbo.SomeTable', N'U') IS NOT NULL
DROP TABLE dbo.SomeTable;

CREATE TABLE dbo.SomeTable
(
    rn int NOT NULL IDENTITY(1,1)
        CONSTRAINT pk
        PRIMARY KEY NONCLUSTERED
    , i int NOT NULL INDEX i 
    , d sysname NOT NULL
) ON [PRIMARY] WITH (DATA_COMPRESSION = NONE);

CREATE UNIQUE CLUSTERED INDEX cx ON dbo.SomeTable (i, d);

CREATE STATISTICS d ON dbo.SomeTable (d) WITH FULLSCAN;

INSERT INTO dbo.SomeTable (d, i)
SELECT c1.name, c1.id
FROM sys.syscolumns c1;

이 쿼리는 각 통계 객체가 마지막으로 업데이트 된 날짜를 보여줍니다.

SELECT ObjectName = sc.name + N'.' + o.name
    , StatsName = s.name
    , StatsDate = STATS_DATE(s.object_id, s.stats_id)
FROM sys.stats s
    INNER JOIN sys.objects o ON s.object_id = o.object_id
    INNER JOIN sys.schemas sc ON o.schema_id = sc.schema_id
WHERE sc.name = N'dbo'
    AND o.name = N'SomeTable';

결과는 아직 업데이트가 수행되지 않았 음을 보여줍니다. 방금 표를 만들었으므로 정확합니다.

╔ ================ ╦ ============ ╦ ============
Name ObjectName ║ StatsName ║ 통계 날짜 ║
╠ ================ ╬ ============ ╬ ============
bo dbo.SomeTable ║ cx ║ NULL ║
bo dbo.SomeTable ║ i ║ NULL ║
bo dbo.SomeTable ║ pk ║ NULL ║
bo dbo.SomeTable ║ d ║ NULL ║
╚ ================ ╩ ============ ╩ ============

전체 테이블을 다시 작성하고 통계가 업데이트되는지 확인하십시오.

ALTER TABLE dbo.SomeTable REBUILD;

SELECT ObjectName = sc.name + N'.' + o.name
    , StatsName = s.name
    , StatsDate = STATS_DATE(s.object_id, s.stats_id)
FROM sys.stats s
    INNER JOIN sys.objects o ON s.object_id = o.object_id
    INNER JOIN sys.schemas sc ON o.schema_id = sc.schema_id
WHERE sc.name = N'dbo'
    AND o.name = N'SomeTable';
╔ ================ ╦ ============ ╦ ====================== ==== ╗
Name ObjectName ║ StatsName ║ 통계 날짜 ║
╠ ================ ╬ ============ ╬ ====================== ==== ╣
bo dbo.SomeTable ║ cx ║ 2018-09-17 14 : 09 : 13.590 ║
bo dbo.SomeTable ║ i ║ NULL ║
bo dbo.SomeTable ║ pk ║ NULL ║
bo dbo.SomeTable ║ d ║ NULL ║
╚ ================ ╩ ============ ╩ ====================== ==== ╝

결과는 클러스터형 인덱스 통계 만 업데이트되었음을 보여줍니다 .

다음으로 개별 UPDATE STATS작업 을 수행 합니다.

UPDATE STATISTICS dbo.SomeTable(d) WITH FULLSCAN;

SELECT ObjectName = sc.name + N'.' + o.name
    , StatsName = s.name
    , StatsDate = STATS_DATE(s.object_id, s.stats_id)
FROM sys.stats s
    INNER JOIN sys.objects o ON s.object_id = o.object_id
    INNER JOIN sys.schemas sc ON o.schema_id = sc.schema_id
WHERE sc.name = N'dbo'
    AND o.name = N'SomeTable';

보시다시피, d열의 통계를 업데이트했습니다 .

╔ ================ ╦ ============ ╦ ====================== ==== ╗
Name ObjectName ║ StatsName ║ 통계 날짜 ║
╠ ================ ╬ ============ ╬ ====================== ==== ╣
bo dbo.SomeTable ║ cx ║ 2018-09-17 14 : 09 : 13.590 ║
bo dbo.SomeTable ║ i ║ NULL ║
bo dbo.SomeTable ║ pk ║ NULL ║
bo dbo.SomeTable ║ d ║ 2018-09-17 14 : 09 : 13.597 ║
╚ ================ ╩ ============ ╩ ====================== ==== ╝

이제 전체 테이블의 통계를 업데이트하겠습니다.

UPDATE STATISTICS dbo.SomeTable WITH FULLSCAN;

SELECT ObjectName = sc.name + N'.' + o.name
    , StatsName = s.name
    , StatsDate = STATS_DATE(s.object_id, s.stats_id)
FROM sys.stats s
    INNER JOIN sys.objects o ON s.object_id = o.object_id
    INNER JOIN sys.schemas sc ON o.schema_id = sc.schema_id
WHERE sc.name = N'dbo'
    AND o.name = N'SomeTable';
╔ ================ ╦ ============ ╦ ====================== ==== ╗
Name ObjectName ║ StatsName ║ 통계 날짜 ║
╠ ================ ╬ ============ ╬ ====================== ==== ╣
bo dbo.SomeTable ║ cx ║ 2018-09-17 14 : 09 : 13.600 ║
bo dbo.SomeTable ║ i ║ 2018-09-17 14 : 09 : 13.600 ║
bo dbo.SomeTable ║ pk ║ 2018-09-17 14 : 09 : 13.603 ║
bo dbo.SomeTable ║ d ║ 2018-09-17 14 : 09 : 13.607 ║
╚ ================ ╩ ============ ╩ ====================== ==== ╝

보시다시피, 모든 통계가 업데이트되도록하는 유일한 방법은 각 통계를 수동으로 업데이트하거나 전체 테이블을로 업데이트하는 것입니다 UPDATE STATISTICS (table);.


@JeremyWeir-위의 질문에 방금 추가 한 예제 코드에서 알 수 있듯이 업데이트 된 통계는 ALTER INDEX ... REBUILD또는 UPDATE STATISTICS문을 통해 명시 적으로 업데이트 된 통계 입니다. 테이블 자체가 재 구축되면 클러스터형 인덱스 통계 만 업데이트됩니다. 참고로, 기본 키와 클러스터형 인덱스가 반드시 동일한 인덱스 객체에서 지원되는 것은 아닙니다.
Max Vernon

5

SQL Server 통계에 대한 Microsoft Docs 페이지 에는 다음이 표시됩니다.

인덱스 다시 작성, 조각 모음 또는 재구성과 같은 작업은 데이터 배포를 변경하지 않습니다. 따라서 ALTER INDEX REBUILD, DBCC DBREINDEX, DBCC INDEXDEFRAG 또는 ALTER INDEX REORGANIZE 작업을 수행 한 후 통계를 업데이트 할 필요가 없습니다 . ALTER INDEX REBUILD 또는 DBCC DBREINDEX를 사용하여 테이블 또는 뷰에서 인덱스를 재 구축 할 때 Query Optimizer는 통계를 업데이트하지만이 통계 업데이트는 인덱스를 다시 생성 한 결과입니다. Query Optimizer는 DBCC INDEXDEFRAG 또는 ALTER INDEX REORGANIZE 조작 후 통계를 업데이트하지 않습니다.

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