Một trong những cách tuyệt vời để tìm hiểu về các lỗi trong SQL Server là đọc qua các ghi chú phát hành cho Bản cập nhật tích lũy và Gói dịch vụ khi chúng xuất hiện. Tuy nhiên, đôi khi đây cũng là một cách tuyệt vời để tìm hiểu về các cải tiến đối với SQL Server.
Cập nhật tích lũy 6 cho SQL Server 2014 Gói dịch vụ 1 đã giới thiệu một cờ theo dõi mới, 7471, thay đổi hành vi khóa của các tác vụ CẬP NHẬT THỐNG KÊ trong SQL Server (xem KB # 3156157). Trong bài đăng này, chúng tôi sẽ xem xét sự khác biệt trong hành vi khóa và vị trí cờ theo dõi này có thể hữu ích.
Để thiết lập môi trường demo thích hợp cho bài đăng này, tôi đã sử dụng cơ sở dữ liệu AdventureWorks2014 và tạo bảng SalesOrderDetail phiên bản phóng to dựa trên tập lệnh có sẵn trên blog của tôi. Bảng SalesOrderDetailEnlarged đã được phóng to với kích thước 2GB để CẬP NHẬT THỐNG KÊ VỚI FULLSCAN các hoạt động có thể được thực hiện đồng thời với các thống kê khác nhau trên bảng. Sau đó, tôi đã sử dụng sp_whoisactive để kiểm tra các khóa được giữ bởi cả hai phiên.
Hành vi không có TF 7471
Hành vi mặc định của SQL Server yêu cầu một khóa riêng (X) trên tài nguyên OBJECT.UPDSTATS cho bảng bất cứ khi nào lệnh UPDATE STATISTICS được thực thi đối với bảng. Bạn có thể thấy điều này trong đầu ra sp_whoisactive cho hai lần thực thi đồng thời CẬP NHẬT THỐNG KÊ VỚI FULLSCAN đối với bảng Sales.SalesOrderDetailEnlarged, sử dụng các tên chỉ mục khác nhau để cập nhật thống kê. Điều này dẫn đến việc chặn quá trình thực thi THỐNG KÊ CẬP NHẬT thứ hai cho đến khi lần thực thi đầu tiên hoàn tất.
CẬP NHẬT THỐNG KÊ [Bán hàng]. [SalesOrderDetailEnlarged] ([PK_SalesOrderDetailEnlarged_SalesOrderID_SalesOrderDetailID]) VỚI FULLSCAN;
CẬP NHẬT THỐNG KÊ [Bán hàng]. [SalesOrderDetailEnlarged] ([IX_SalesOrderDetailEnlarged_ProductID]) VỚI FULLSCAN;
Mức độ chi tiết của tài nguyên khóa trên OBJECT.UPDSTATS ngăn cập nhật đồng thời nhiều thống kê trên cùng một bảng. Các cải tiến phần cứng trong những năm gần đây đã thực sự thay đổi các nút thắt tiềm ẩn thường gặp đối với việc triển khai SQL Server và cũng giống như các thay đổi đã được thực hiện đối với DBCC CHECKDB để làm cho nó chạy nhanh hơn, thay đổi hành vi khóa của UPDATE STATISTICS để cho phép cập nhật đồng thời số liệu thống kê trên cùng một bảng có thể giảm đáng kể thời gian bảo trì cho các VLDB, đặc biệt là khi có đủ dung lượng CPU và hệ thống con I / O để cho phép các bản cập nhật đồng thời xảy ra mà không ảnh hưởng đến trải nghiệm của người dùng cuối.
Hành vi với TF 7471
Hành vi khóa với cờ theo dõi 7471 cho phép thay đổi từ yêu cầu khóa riêng (X) trên tài nguyên OBJECT.UPDSTATS sang yêu cầu khóa cập nhật (U) trên tài nguyên METADATA.STATS cho thống kê cụ thể đang được cập nhật, cho phép thực hiện đồng thời của CẬP NHẬT THỐNG KÊ trên cùng một bảng. Kết quả của sp_whoisactive cho cùng một lệnh CẬP NHẬT THỐNG KÊ VỚI FULLCAN với cờ theo dõi được bật được hiển thị bên dưới:
CẬP NHẬT THỐNG KÊ [Bán hàng]. [SalesOrderDetailEnlarged] ([PK_SalesOrderDetailEnlarged_SalesOrderID_SalesOrderDetailID]) VỚI FULLSCAN;
CẬP NHẬT THỐNG KÊ [Bán hàng]. [SalesOrderDetailEnlarged] ([IX_SalesOrderDetailEnlarged_ProductID]) VỚI FULLSCAN;
Đối với VLDB, những thứ đang trở nên phổ biến hơn nhiều, điều này có thể tạo ra sự khác biệt lớn về thời gian thực hiện cập nhật thống kê trên một máy chủ.
Gần đây, tôi đã viết blog về giải pháp bảo trì song song cho SQL Server bằng cách sử dụng tập lệnh bảo trì của Service Broker và Ola Hallengren như một cách để tối ưu hóa các nhiệm vụ bảo trì hàng đêm và giảm thời gian cần thiết để xây dựng lại chỉ mục và cập nhật thống kê trên các máy chủ có nhiều dung lượng CPU và I / O có sẵn. Là một phần của giải pháp đó, tôi đã buộc một thứ tự các nhiệm vụ xếp hàng cho Service Broker để thử và tránh việc thực thi đồng thời đối với cùng một bảng cho cả nhiệm vụ xây dựng lại chỉ mục / tổ chức lại và CẬP NHẬT THỐNG KÊ. Mục đích của việc này là giữ cho công nhân càng bận rộn càng tốt cho đến khi kết thúc nhiệm vụ bảo trì, nơi mọi thứ sẽ tuần tự trong quá trình thực thi dựa trên việc ngăn chặn các nhiệm vụ đồng thời.
Tôi đã thực hiện một số sửa đổi đối với quá trình xử lý trong bài đăng đó để chỉ kiểm tra tác động của cờ theo dõi này chỉ với các bản cập nhật thống kê đồng thời và kết quả ở bên dưới.
Kiểm tra Hiệu suất Cập nhật Thống kê Đồng thời
Để kiểm tra hiệu suất của việc chỉ cập nhật thống kê song song bằng cách sử dụng cấu hình Service Broker, tôi đã bắt đầu bằng cách tạo thống kê cột trên mỗi cột trong cơ sở dữ liệu AdventureWorks2014 bằng cách sử dụng tập lệnh sau để tạo các lệnh DDL sẽ được thực thi.
SỬ DỤNG [AdventureWorks2014] ĐI CHỌN *, 'DROP THỐNG KÊ' + QUOTENAME (c.TABLE_SCHEMA) + '.' + QUOTENAME (c.TABLE_NAME) + '.' + QUOTENAME (c.TABLE_NAME + '_' + c.COLUMN_NAME) + '; GOCREATE STATISTICS' + QUOTENAME (c.TABLE_NAME + '_' + c.COLUMN_NAME) + 'ON' + QUOTENAME (c.TABLE_SCHEMA) + '. ' + QUOTENAME (c.TABLE_NAME) + '(' + QUOTENAME (c.COLUMN_NAME) + ');' + 'ĐI' TỪ INFORMATION_SCHEMA.COLUMNS AS CINNER THAM GIA INFORMATION_SCHEMA.TABLES AS t TRÊN c.TABLE_CATALOG =t.TABLE_CATALOG AND c.TABLE_SCHEMA =t.TABLE_SCHEMA AND c.TABLE_NAME =t.TABLE_NAMEWHERE t.TABLE_TYPE ='BASE TABLE .DATA_TYPE <> N'xml ';Đây không phải là điều mà bạn thường muốn làm, nhưng nó cung cấp cho tôi nhiều thống kê để kiểm tra song song tác động của cờ theo dõi đối với việc cập nhật thống kê đồng thời. Thay vì sắp xếp ngẫu nhiên thứ tự mà tôi xếp các nhiệm vụ vào Service Broker, thay vào đó tôi chỉ xếp các nhiệm vụ khi chúng tồn tại trong bảng CommandLog dựa trên ID của bảng, chỉ cần tăng ID lên một cho đến khi tất cả các lệnh đã được xếp vào hàng đợi để xử lý.
SỬ DỤNG [master]; - Xóa Command LogTRUNCATE TABLE [master]. [Dbo]. [CommandLog]; DECLARE @MaxID INT; CHỌN @MaxID =MAX (ID) TỪ master.dbo.CommandLog; SELECT @MaxID =ISNULL (@MaxID, 1) ---- Tải các tác vụ mới vào Command LogEXEC master.dbo.IndexOptimize @Databases =N'AdventureWorks2014 ', @FragmentationLow =NULL, @FragmentationMedium =NULL, @FragmentationHigh =NULL, @UpdateStatistics ='ALL', @St StatisticsSample =100, @LogToTable ='Y', @Execute ='N'; DECLARE @NewMaxID INTSELECT @NewMaxID =MAX (ID) TỪ master.dbo.CommandLog; SỬ DỤNG msdb; DECLARE @CurrentID INT =@MaxIDWHILE (@CurrentID <=@NewMaxID) BEGIN - Bắt đầu cuộc trò chuyện và gửi thông báo yêu cầu DECLARE @conversation_handle UNIQUEIDENTIFIER; DECLARE @message_body XML; BẮT ĐẦU GIAO DỊCH; BEGIN DIALOG @conversation_handle TỪ DỊCH VỤ [OlaHallengrenMaintenanceTaskService] ĐẾN DỊCH VỤ N'OlaHallengrenMaintenanceTaskService 'TRÊN HỢP ĐỒNG [OlaHallengrenMaintenanceTaskContract] VỚI ENCRYPTION =OFF; SELECT @message_body =N '' + CAST (@CurrentID AS NVARCHAR) + N ' '; GỬI TRÊN CONVERSATION @conversation_handle LOẠI TIN NHẮN [OlaHallengrenMaintenanceTaskMessage] (@message_body); CAM KẾT GIAO DỊCH; SET @CurrentID =@CurrentID + 1; KẾT THÚC KHI TỒN TẠI (CHỌN 1 TỪ OlaHallengrenMaintenanceTaskQueue VỚI (NOLOCK)) BẮT ĐẦU CHỜ ĐỢI TRỪ '00:00:01.000'END WAITFOR DELAY '00:00:06.000 'CHỌN DATEDIFF (mili giây, MIN (Thời gian bắt đầu) ), MAX (Thời gian kết thúc)) TỪ master.dbo.CommandLog; ĐI 10Sau đó, tôi đợi tất cả các tác vụ hoàn thành, đo delta trong thời gian bắt đầu và thời gian kết thúc thực hiện tác vụ và lấy trung bình của mười bài kiểm tra để xác định các cải tiến chỉ để cập nhật thống kê đồng thời bằng cách sử dụng lấy mẫu mặc định và cập nhật quét toàn bộ.
Kết quả thử nghiệm cho thấy ngay cả với việc chặn xảy ra theo hành vi mặc định mà không có cờ theo dõi, các bản cập nhật thống kê được lấy mẫu chạy nhanh hơn 6% và các bản cập nhật quét toàn bộ chạy nhanh hơn 16% với năm luồng xử lý các tác vụ được xếp hàng đợi đến Service Broker. Với cờ theo dõi 7471 được kích hoạt, các bản cập nhật thống kê được lấy mẫu tương tự chạy nhanh hơn 38% và các bản cập nhật quét toàn bộ chạy nhanh hơn 45% với năm luồng xử lý các tác vụ được xếp hàng đợi đến Service Broker.
Những thách thức tiềm tàng với TF 7471
Kết quả thử nghiệm hấp dẫn như vậy, không có gì trên thế giới này là miễn phí và trong thử nghiệm ban đầu của tôi về điều này, tôi đã gặp một số vấn đề với kích thước của máy ảo mà tôi đang sử dụng trên máy tính xách tay của mình, điều này đã tạo ra các vấn đề về khối lượng công việc.
Ban đầu, tôi đang thử nghiệm bảo trì song song bằng cách sử dụng máy ảo 4vCPU với RAM 4GB mà tôi đã thiết lập riêng cho mục đích này. Khi tôi bắt đầu tăng số lượng MAX_QUEUE_READERS cho quy trình kích hoạt trong Service Broker, tôi bắt đầu gặp sự cố với RESOURCE_SEMAPHORE phải đợi khi cờ theo dõi được bật, cho phép cập nhật song song thống kê trên các bảng mở rộng trong cơ sở dữ liệu AdventureWorks2014 của tôi do yêu cầu cấp bộ nhớ cho mỗi lệnh CẬP NHẬT THỐNG KÊ đang chạy. Điều này đã được giảm bớt bằng cách thay đổi cấu hình VM thành RAM 16GB nhưng đây là điều cần theo dõi và lưu ý khi thực hiện các tác vụ song song trên các bảng lớn hơn, bao gồm bảo trì chỉ mục, vì việc cấp bộ nhớ bị đói cũng sẽ ảnh hưởng đến các yêu cầu của người dùng cuối có thể đang cố gắng thực thi và cũng cần cấp bộ nhớ lớn hơn.
Nhóm sản phẩm cũng đã viết blog về cờ theo dõi này và trong bài đăng của họ, họ cảnh báo rằng các tình huống bế tắc có thể xảy ra trong quá trình cập nhật thống kê đồng thời trong khi số liệu thống kê cũng đang được tạo. Đây không phải là điều tôi đã gặp phải trong quá trình thử nghiệm của mình, nhưng nó chắc chắn là điều cần lưu ý (Kendra Little cũng cảnh báo về điều đó). Do đó, khuyến nghị của họ là cờ theo dõi này chỉ được bật trong quá trình thực thi nhiệm vụ bảo trì song song và sau đó nó sẽ bị vô hiệu hóa trong các khoảng thời gian khối lượng công việc bình thường.
Hãy tận hưởng!