Có một chỉ số cập nhật lại số liệu thống kê?


43

Tôi đã tham gia khóa học MS10775A tuần trước và một câu hỏi được đưa ra mà huấn luyện viên không thể trả lời một cách đáng tin cậy là:

Có một chỉ số lại cập nhật số liệu thống kê?

Chúng tôi thấy các cuộc thảo luận trực tuyến tranh luận cả về điều đó và nó không.


Thật hữu ích khi lưu ý rằng việc REINDEXcập nhật số liệu thống kê cột là tác dụng phụ của việc xây dựng lại chỉ mục - bạn không cần cập nhật số liệu thống kê. Dữ liệu trong bảng không thay đổi. Đó là cùng một dữ liệu, chỉ có một) di chuyển vị trí của nó trên đĩa quay (khi một trang được sắp xếp lại) hoặc b) ngồi trong một trang khác (trong trường hợp xây dựng lại). Vì vậy: một chỉ mục lại không cập nhật (một số) số liệu thống kê: không cần phải làm điều đó.
Ian Boyd

Câu trả lời:


51

Bạn có thể ghi nhớ những điều sau đây khi quan tâm đến việc cập nhật số liệu thống kê (được sao chép từ Chỉ mục xây dựng lại so với Cập nhật số liệu thống kê (Benjamin Nevarez)

  1. Theo mặc định, UPDATE STATISTICScâu lệnh chỉ sử dụng một mẫu các bản ghi của bảng. Sử dụng UPDATE STATISTICS WITH FULLSCANsẽ quét toàn bộ bảng.

  2. Theo mặc định, UPDATE STATISTICScâu lệnh cập nhật cả thống kê chỉ mục và cột. Sử dụng COLUMNStùy chọn sẽ chỉ cập nhật số liệu thống kê cột. Sử dụng INDEXtùy chọn sẽ chỉ cập nhật số liệu thống kê chỉ mục.

  3. Việc xây dựng lại một chỉ mục , ví dụ bằng cách sử dụng ALTER INDEX … REBUILDcũng sẽ cập nhật số liệu thống kê chỉ mục tương đương với việc sử dụng WITH FULLSCAN trừ khi bảng được phân vùng, trong trường hợp đó, số liệu thống kê chỉ được lấy mẫu (áp dụng cho SQL Server 2012 trở lên).

  4. Thống kê được tạo thủ công bằng cách sử dụng CREATE STATISTICSkhông được cập nhật bởi bất kỳ ALTER INDEX ... REBUILDhoạt động, bao gồm ALTER TABLE ... REBUILD. ALTER TABLE ... REBUILDkhông cập nhật số liệu thống kê cho chỉ mục được nhóm, nếu một được xác định trên bảng đang được xây dựng lại.

  5. Sắp xếp lại một chỉ mục , ví dụ sử dụng ALTER INDEX … REORGANIZEkhông cập nhật bất kỳ số liệu thống kê nào.

Câu trả lời ngắn gọn là bạn cần sử dụng UPDATE STATISTICSđể cập nhật số liệu thống kê cột và việc xây dựng lại chỉ mục sẽ chỉ cập nhật thống kê chỉ mục. Bạn có thể buộc cập nhật cho tất cả các số liệu thống kê trên một bảng, bao gồm thống kê chỉ mục và thống kê được tạo thủ công, bằng UPDATE STATISTICS (tablename) WITH FULLSCAN;cú pháp.

Đoạn mã sau minh họa các quy tắc được gói gọn ở trên:

Đầu tiên, chúng ta sẽ tạo một bảng có một vài cột và một chỉ mục được nhóm:

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;

Truy vấn này hiển thị ngày mà mỗi đối tượng thống kê được cập nhật lần cuối:

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';

Kết quả cho thấy chưa có cập nhật nào diễn ra, điều này là chính xác vì chúng ta vừa tạo bảng:

╔═══════════════╦═══════════╦═══════════╗
ObjectName StatsName StatsDate
╠═══════════════╬═══════════╬═══════════╣
║ dbo.SomeTable cx ║ NULL
║ dbo.SomeTable i ║ NULL
║ dbo.SomeTable pk NULL
║ dbo.SomeTable d ║ NULL
╚═══════════════╩═══════════╩═══════════╝

Hãy xây dựng lại toàn bộ bảng và xem nếu cập nhật số liệu thống kê:

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';
╔═══════════════╦═══════════╦═════════════════════ ════╗
ObjectName StatsName StatsDate
╠═══════════════╬═══════════╬═════════════════════ ════╣
║ dbo.SomeTable cx 2018-09-17 14: 09: 13,590
║ dbo.SomeTable i ║ NULL
║ dbo.SomeTable pk NULL
║ dbo.SomeTable d ║ NULL
╚═══════════════╩═══════════╩═════════════════════ ════╝

Kết quả chỉ hiển thị các số liệu thống kê chỉ số cụm được cập nhật.

Tiếp theo, chúng tôi thực hiện một UPDATE STATShoạt động riêng biệt :

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';

Như bạn có thể thấy, chúng tôi vừa cập nhật số liệu thống kê trên dcột:

╔═══════════════╦═══════════╦═════════════════════ ════╗
ObjectName StatsName StatsDate
╠═══════════════╬═══════════╬═════════════════════ ════╣
║ dbo.SomeTable cx 2018-09-17 14: 09: 13,590
║ dbo.SomeTable i ║ NULL
║ dbo.SomeTable pk NULL
║ dbo.SomeTable d ║ 2018-09-17 14: 09: 13,597
╚═══════════════╩═══════════╩═════════════════════ ════╝

Bây giờ, chúng tôi sẽ cập nhật số liệu thống kê trên toàn bộ bảng:

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';
╔═══════════════╦═══════════╦═════════════════════ ════╗
ObjectName StatsName StatsDate
╠═══════════════╬═══════════╬═════════════════════ ════╣
║ dbo.SomeTable cx 2018-09-17 14: 09: 13.600
║ dbo.SomeTable i ║ 2018-09-17 14: 09: 13.600
║ dbo.SomeTable pk 2018-09-17 14: 09: 13.603
Dbo.SomeTable d ║ 2018-09-17 14: 09: 13.607
╚═══════════════╩═══════════╩═════════════════════ ════╝

Như bạn có thể thấy, cách duy nhất để chắc chắn tất cả các số liệu thống kê được cập nhật là cập nhật từng cái một cách thủ công hoặc cập nhật toàn bộ bảng với UPDATE STATISTICS (table);.


@Jeremy Weir - như bạn có thể thấy từ mã ví dụ tôi vừa thêm vào câu hỏi ở trên, số liệu thống kê duy nhất được cập nhật là những số liệu được cập nhật rõ ràng thông qua một ALTER INDEX ... REBUILDhoặc một UPDATE STATISTICStuyên bố. Nếu bảng được xây dựng lại, chỉ có các thống kê chỉ mục được nhóm được cập nhật. FYI, một khóa chính và một chỉ mục được nhóm không nhất thiết phải được hỗ trợ bởi cùng một đối tượng chỉ mục.
Max Vernon

5

Trang Microsoft Docs cho SQL Server thống kê trạng thái :

Các hoạt động như xây dựng lại, chống phân mảnh hoặc sắp xếp lại một chỉ mục không làm thay đổi việc phân phối dữ liệu. Do đó, bạn không cần cập nhật số liệu thống kê sau khi thực hiện các hoạt động ALTER INDEX REBUILD, DBCC DBREINDEX, DBCC INDEXDEFRAG hoặc ALTER INDEX REORGANIZE . Trình tối ưu hóa truy vấn cập nhật số liệu thống kê khi bạn xây dựng lại một chỉ mục trên bảng hoặc chế độ xem với ALTER INDEX REBUILD hoặc DBCC DBREINDEX, tuy nhiên bản cập nhật thống kê này là sản phẩm phụ của việc tạo lại chỉ mục. Trình tối ưu hóa truy vấn không cập nhật số liệu thống kê sau các hoạt động DBCC INDEXDEFRAG hoặc ALTER INDEX REORGANIZE.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.