Benjamin Nevarez là một nhà tư vấn độc lập có trụ sở tại Los Angeles, California, người chuyên về điều chỉnh và tối ưu hóa truy vấn SQL Server. Ông là tác giả của “SQL Server 2014 Query Tuning &Optimization” và “Inside the SQL Server Query Optimizer” và là đồng tác giả của “SQL Server 2012 Internals”. Với hơn 20 năm kinh nghiệm trong lĩnh vực cơ sở dữ liệu quan hệ, Benjamin cũng là diễn giả tại nhiều hội nghị SQL Server, bao gồm PASS Summit, SQL Server Connections và SQLBits. Có thể tìm thấy blog của Benjamin tại http://www.benjaminnevarez.com và bạn cũng có thể liên hệ với anh ấy qua e-mail tại quản trị viên tại benjaminnevarez dot com và trên twitter tại @BenjaminNevarez.
Một vấn đề lớn với việc cập nhật thống kê trong các bảng lớn trong SQL Server là toàn bộ bảng luôn phải được quét, ví dụ:khi sử dụng WITH FULLSCAN
tùy chọn, ngay cả khi chỉ có dữ liệu gần đây đã thay đổi. Điều này cũng đúng khi sử dụng phân vùng:ngay cả khi chỉ phân vùng mới nhất đã thay đổi kể từ lần cuối cùng thống kê được cập nhật, việc cập nhật lại thống kê vẫn cần thiết để quét toàn bộ bảng bao gồm tất cả các phân vùng không thay đổi. Số liệu thống kê tăng dần, một tính năng mới của SQL Server 2014, có thể giúp giải quyết vấn đề này.
Sử dụng thống kê gia tăng, bạn chỉ có thể cập nhật phân vùng hoặc các phân vùng mà bạn cần và thông tin trên các phân vùng này sẽ được hợp nhất với thông tin hiện có để tạo đối tượng thống kê cuối cùng. Một ưu điểm khác của thống kê gia tăng là tỷ lệ thay đổi dữ liệu cần thiết để kích hoạt cập nhật thống kê tự động hiện hoạt động ở cấp phân vùng, về cơ bản có nghĩa là bây giờ chỉ cần 20% số hàng thay đổi (thay đổi trên cột thống kê hàng đầu) trên mỗi phân vùng. Rất tiếc, biểu đồ vẫn bị giới hạn ở 200 bước cho toàn bộ đối tượng thống kê trong phiên bản SQL Server này.
Hãy để chúng tôi xem xét một ví dụ về cách bạn có thể cập nhật số liệu thống kê ở cấp phân vùng để khám phá hành vi của nó ít nhất kể từ SQL Server 2014 CTP2. Trước tiên, chúng ta cần tạo một bảng được phân vùng bằng cơ sở dữ liệu AdventureWorks2012:
CREATE PARTITION FUNCTION TransactionRangePF1 (DATETIME) AS RANGE RIGHT FOR VALUES ( '20071001', '20071101', '20071201', '20080101', '20080201', '20080301', '20080401', '20080501', '20080601', '20080701', '20080801' ); GO CREATE PARTITION SCHEME TransactionsPS1 AS PARTITION TransactionRangePF1 TO ( [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY] ); GO CREATE TABLE dbo.TransactionHistory ( TransactionID INT NOT NULL, -- not bothering with IDENTITY here ProductID INT NOT NULL, ReferenceOrderID INT NOT NULL, ReferenceOrderLineID INT NOT NULL DEFAULT (0), TransactionDate DATETIME NOT NULL DEFAULT (GETDATE()), TransactionType NCHAR(1) NOT NULL, Quantity INT NOT NULL, ActualCost MONEY NOT NULL, ModifiedDate DATETIME NOT NULL DEFAULT (GETDATE()), CONSTRAINT CK_TransactionType CHECK (UPPER(TransactionType) IN (N'W', N'S', N'P')) ) ON TransactionsPS1 (TransactionDate); GO
Lưu ý:Để biết chi tiết về phân vùng và CREATE PARTITION FUNCTION / SCHEME
vui lòng tham khảo Bảng phân vùng và Chỉ mục trong Sách Trực tuyến.
Chúng tôi hiện có dữ liệu để điền 12 phân vùng. Chúng ta hãy bắt đầu bằng cách chỉ điền 11.
INSERT INTO dbo.TransactionHistory SELECT * FROM Production.TransactionHistory WHERE TransactionDate < '2008-08-01';
Nếu được yêu cầu, bạn có thể sử dụng câu lệnh sau để kiểm tra nội dung của các phân vùng:
SELECT * FROM sys.partitions WHERE object_id = OBJECT_ID('dbo.TransactionHistory');
Hãy để chúng tôi tạo một đối tượng thống kê tăng dần bằng cách sử dụng CREATE STATISTICS
câu lệnh với INCREMENTAL
mới mệnh đề được đặt thành ON
(OFF
là mặc định):
CREATE STATISTICS incrstats ON dbo.TransactionHistory(TransactionDate) WITH FULLSCAN, INCREMENTAL = ON;
Bạn cũng có thể tạo thống kê gia tăng trong khi tạo chỉ mục bằng STATISTICS_INCREMENTAL
mới mệnh đề của CREATE INDEX
tuyên bố.
Bạn có thể kiểm tra đối tượng thống kê đã tạo bằng cách sử dụng DBCC
:
DBCC SHOW_STATISTICS('dbo.TransactionHistory', incrstats);
Trong số những thứ khác, bạn sẽ nhận thấy rằng biểu đồ có 200 bước (chỉ 3 bước cuối cùng được hiển thị ở đây):
RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | |
198 | 2008-07-25 00:00:00.000 | 187 | 100 | 2 |
199 | 2008-07-27 00:00:00.000 | 103 | 101 | 1 |
200 | 2008-07-31 00:00:00.000 | 281 | 131 | 3 |
Kết quả DBCC ban đầu
Vì vậy, chúng tôi đã có tối đa các bước trong một đối tượng thống kê. Điều gì sẽ xảy ra nếu bạn thêm dữ liệu vào một phân vùng mới? Hãy để chúng tôi thêm dữ liệu vào phân vùng 12:
INSERT INTO dbo.TransactionHistory SELECT * FROM Production.TransactionHistory WHERE TransactionDate >= '2008-08-01';
Bây giờ, chúng tôi cập nhật đối tượng thống kê bằng cách sử dụng câu lệnh sau:
UPDATE STATISTICS dbo.TransactionHistory(incrstats) WITH RESAMPLE ON PARTITIONS(12);
Lưu ý cú pháp mới chỉ định phân vùng, nơi bạn có thể chỉ định nhiều phân vùng, được phân tách bằng dấu phẩy. UPDATE STATISTICS
câu lệnh đọc các phân vùng được chỉ định và sau đó hợp nhất kết quả của chúng với đối tượng thống kê hiện có để xây dựng thống kê toàn cục. Lưu ý RESAMPLE
mệnh đề; điều này là bắt buộc vì thống kê phân vùng cần có cùng tỷ lệ mẫu được hợp nhất để xây dựng thống kê toàn cầu. Mặc dù chỉ quét phân vùng được chỉ định, bạn có thể thấy rằng SQL Server đã sắp xếp lại biểu đồ. Ba bước cuối cùng hiện hiển thị dữ liệu cho phân vùng đã thêm. Bạn cũng có thể so sánh biểu đồ gốc với biểu đồ mới để biết những khác biệt nhỏ khác:
RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | |
197 | 2008-07-31 00:00:00.000 | 150 | 131 | 2 |
198 | 2008-08-12 00:00:00.000 | 300 | 36 | 9 |
199 | 2008-08-22 00:00:00.000 | 229 | 43 | 7 |
200 | 2008-09-03 00:00:00.000 | 363 | 37 | 11 |
Kết quả DBCC sau khi cập nhật gia tăng
Nếu vì bất kỳ lý do gì bạn muốn tắt thống kê gia tăng, bạn có thể sử dụng câu lệnh sau để quay lại hành vi ban đầu (hoặc tùy chọn chỉ cần thả đối tượng thống kê và tạo một đối tượng mới).
UPDATE STATISTICS dbo.TransactionHistory(incrstats) WITH FULLSCAN, INCREMENTAL = OFF;
Sau khi vô hiệu hóa số liệu thống kê gia tăng, cố gắng cập nhật một phân vùng như được hiển thị trước đó sẽ trả về thông báo lỗi sau:
Msg 9111, Mức 16, Trạng thái 1CẬP NHẬT THỐNG KÊ TRÊN CÁC PHẦN Cú pháp không được hỗ trợ cho các thống kê không gia tăng.
Cuối cùng, bạn cũng có thể bật thống kê gia tăng cho thống kê tự động của mình ở cấp cơ sở dữ liệu, nếu cần. Điều này yêu cầu INCREMENTAL = ON
trong ALTER DATABASE
và rõ ràng cũng yêu cầu AUTO_CREATE_STATISTICS
đặt thành ON
.