Câu trả lời:
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)
Theo mặc định, UPDATE STATISTICS
câ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 FULLSCAN
sẽ quét toàn bộ bảng.
Theo mặc định, UPDATE STATISTICS
câu lệnh cập nhật cả thống kê chỉ mục và cột. Sử dụng COLUMNS
tùy chọn sẽ chỉ cập nhật số liệu thống kê cột. Sử dụng INDEX
tùy chọn sẽ chỉ cập nhật số liệu thống kê chỉ mục.
Việc xây dựng lại một chỉ mục , ví dụ bằng cách sử dụng ALTER INDEX … REBUILD
cũ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).
Thống kê được tạo thủ công bằng cách sử dụng CREATE STATISTICS
không được cập nhật bởi bất kỳ ALTER INDEX ... REBUILD
hoạt động, bao gồm ALTER TABLE ... REBUILD
. ALTER TABLE ... REBUILD
khô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.
Sắp xếp lại một chỉ mục , ví dụ sử dụng ALTER INDEX … REORGANIZE
khô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 STATS
hoạ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 d
cộ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);
.
ALTER INDEX ... REBUILD
hoặc một UPDATE STATISTICS
tuyê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.
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.
REINDEX
cậ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 đó.