Database
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Database

Nắm bắt các cảnh báo về kế hoạch thực thi bằng cách sử dụng Sự kiện mở rộng

Chúng tôi sẽ giảng dạy IEPTO2 ở Dublin trong tuần này (và nếu Ireland không có trong danh sách những địa điểm bạn nên đến trong cuộc đời này, bạn phải thêm nó vào… điều đó thật tuyệt vời ở đây) và hôm nay tôi đã hoàn thành mô-đun Phân tích kế hoạch truy vấn. Một điều tôi đề cập là những điều thú vị bạn có thể tìm thấy trong kế hoạch truy vấn, ví dụ:

  • NoJoinPredicate (2005 trở lên)
  • ColumnsWithNoSt Statistics (2005 trở lên)
  • UnmishedIndexes (2008 trở lên)
  • PlanAffectingConvert (2012 trở lên)

Những thuộc tính này rất tốt để tìm kiếm khi bạn đang xem xét một kế hoạch hoặc một nhóm kế hoạch khi bạn đang điều chỉnh. Nhưng nếu bạn muốn chủ động hơn một chút, bạn có thể bắt đầu khai thác bộ nhớ cache của kế hoạch và tìm kiếm chúng ở đó. Tất nhiên, làm như vậy yêu cầu viết một số XQuery, vì các kế hoạch là XML (để biết chi tiết về lược đồ showplan, hãy xem:http://schemas.microsoft.com/sqlserver/2004/07/showplan/). Tôi không thích XML, mặc dù không phải vì thiếu cố gắng và khi một trong những người tham dự hỏi liệu bạn có thể nắm bắt các truy vấn có thuộc tính NoJoinPredicate thông qua Sự kiện mở rộng hay không, tôi đã nghĩ:“Thật là một ý tưởng tuyệt vời, tôi sẽ phải kiểm tra . ”

Chắc chắn rồi, có một Sự kiện cho điều đó. Có một Sự kiện cho cả bốn sự kiện mà tôi đã liệt kê ở trên:

  • Missing_join_predicate
  • thiếu_sản_lượng_thống kê
  • chưa đối sánh_filtered_indexes
  • plan_affecting_convert

Tốt đẹp. Việc thiết lập những điều này trong phiên Sự kiện mở rộng là khá đơn giản. Trong trường hợp này, tôi khuyên bạn nên sử dụng mục tiêu event_file, vì bạn có thể sẽ bắt đầu phiên sự kiện và để nó chạy một chút trước khi bạn quay lại và xem lại kết quả đầu ra. Tôi đã bao gồm một số hành động, với hy vọng rằng những sự kiện này không gây ra điều đó thường xuyên, vì vậy chúng tôi sẽ không thêm quá nhiều chi phí ở đây. Tôi đã bao gồm sql_text mặc dù đó không phải là hành động mà bạn thực sự nên dựa vào. Jonathan đã thảo luận về điều này trước đây, nhưng sql_text chỉ cung cấp cho bạn bộ đệm đầu vào, vì vậy bạn có thể không nhận được toàn bộ câu chuyện cho truy vấn. Vì lý do đó, tôi cũng bao gồm plan_handle. Lưu ý rằng, tùy thuộc vào thời điểm bạn tìm kiếm gói, gói đó có thể không còn trong bộ nhớ cache của gói.

-- Remove event session if it exists
IF EXISTS (SELECT 1 FROM [sys].[server_event_sessions]
WHERE [name] = 'InterestingPlanEvents')
BEGIN
  DROP EVENT SESSION [InterestingPlanEvents] ON SERVER
END
GO
 
-- Define event session
CREATE EVENT SESSION [InterestingPlanEvents]
ON SERVER
ADD EVENT sqlserver.missing_column_statistics
(
  ACTION(sqlserver.database_id,sqlserver.plan_handle,sqlserver.sql_text)
  WHERE ([package0].[equal_boolean]([sqlserver].[is_system],(0))
    AND [sqlserver].[database_id]>(4))
),
ADD EVENT sqlserver.missing_join_predicate
(
  ACTION(sqlserver.database_id,sqlserver.plan_handle,sqlserver.sql_text)
  WHERE ([sqlserver].[is_system]=(0) AND [sqlserver].[database_id]>(4))
),
ADD EVENT sqlserver.plan_affecting_convert
(
  ACTION(sqlserver.database_id,sqlserver.plan_handle,sqlserver.sql_text)
  WHERE ([package0].[equal_boolean]([sqlserver].[is_system],(0))
    AND [sqlserver].[database_id]>(4))
),
ADD EVENT sqlserver.unmatched_filtered_indexes
(
  ACTION(sqlserver.plan_handle,sqlserver.sql_text)
  WHERE ([package0].[equal_boolean]([sqlserver].[is_system],(0))
    AND [sqlserver].[database_id]>(4))
)
ADD TARGET package0.event_file
(
  SET filename=N'C:\temp\InterestingPlanEvents' /* change location if appropriate */
)
WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,
MAX_DISPATCH_LATENCY=5 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,
TRACK_CAUSALITY=ON,STARTUP_STATE=OFF)
GO
 
-- Start the event session
ALTER EVENT SESSION [InterestingPlanEvents] ON SERVER STATE=START;
GO

Khi chúng tôi đã thiết lập và chạy phiên sự kiện, chúng tôi có thể tạo các sự kiện này bằng mã mẫu bên dưới. Lưu ý rằng mã này giả định một bản cài đặt mới của AdventureWorks2014. Nếu không có, bạn có thể không thấy sự kiện Thiếu_column_st Statistics kích hoạt nếu bạn đang truy vấn cột [HireDate] trong [HumanResources]. [Employee].

-- These queries assume a FRESH restore of AdventureWorks2014
ALTER DATABASE [AdventureWorks2014] SET AUTO_CREATE_STATISTICS OFF;
GO
 
USE [AdventureWorks2014];
GO
 
CREATE INDEX [NCI_SalesOrderHeader] ON [Sales].[SalesOrderHeader] (
[PurchaseOrderNumber], [CustomerID], [TotalDue], [DueDate]
)
WHERE [SubTotal] > 10000.00;
GO
 
/*
No join predicate
NOTE: We clear procedure here because the event ONLY fires for the *initial* compilation
*/
DBCC FREEPROCCACHE; /* Not for production use */
 
SELECT [h].[SalesOrderID], [d].[SalesOrderDetailID], [h].[CustomerID]
FROM [Sales].[SalesOrderDetail] [d],
[Sales].[SalesOrderHeader] [h]
WHERE [d].[ProductID] = 897;
GO
 
-- Columns with no statistics
SELECT [BusinessEntityID], [NationalIDNumber], [JobTitle], [HireDate], [ModifiedDate]
FROM [HumanResources].[Employee]
WHERE [HireDate] >= '2013-01-01';
GO
 
-- Unmatched Index
DECLARE @Total MONEY = 10000.00;
 
SELECT [PurchaseOrderNumber], [CustomerID], [TotalDue], [DueDate]
FROM [Sales].[SalesOrderHeader]
WHERE [SubTotal] > @Total;
GO
 
-- Plan Affecting Convert
SELECT [BusinessEntityID], [NationalIDNumber], [JobTitle], [HireDate], [ModifiedDate]
FROM [HumanResources].[Employee]
WHERE [NationalIDNumber] = 345106466;
GO
 
ALTER EVENT SESSION [InterestingPlanEvents]
ON SERVER
STATE=STOP;
GO
 
DROP EVENT SESSION [InterestingPlanEvents]
ON SERVER;
GO

LƯU Ý:Sau khi bạn hoàn tất việc kéo các kế hoạch từ bộ nhớ cache, bạn có thể chạy câu lệnh ALTER để bật tùy chọn thống kê tạo tự động. Làm như vậy tại thời điểm này sẽ xóa bộ nhớ cache của kế hoạch và bạn sẽ phải bắt đầu lại tất cả với thử nghiệm của mình. (Và cũng đợi cho đến khi bạn hoàn thành để giảm chỉ mục.)

ALTER DATABASE [AdventureWorks2014] SET AUTO_CREATE_STATISTICS ON;
GO
 
DROP INDEX [NCI_SalesOrderHeader] ON [Sales].[SalesOrderHeader];
GO

Vì tôi đã dừng phiên sự kiện, tôi sẽ mở tệp đầu ra trong SSMS để xem những gì chúng tôi đã chụp:

Kết quả từ Sự kiện mở rộng

Đối với truy vấn đầu tiên của chúng tôi với một vị từ nối bị thiếu, chúng tôi có một sự kiện hiển thị và tôi có thể thấy văn bản cho truy vấn trong trường sql_text. Tuy nhiên, điều tôi thực sự muốn là xem lại kế hoạch, vì vậy tôi có thể lấy plan_handle và kiểm tra sys.dm_exec_query_plan:

SELECT query_plan FROM sys.dm_exec_query_plan
(0x06000700E2200333405DD12C0000000001000000000000000000000000000000000000000000000000000000);

Và mở nó trong SQL Sentry Plan Explorer:

Thiếu vị từ tham gia

Kế hoạch có một chỉ báo trực quan về vị từ nối bị thiếu trong vòng lặp lồng nhau (dấu X màu đỏ) và nếu tôi di chuột qua nó, tôi sẽ thấy cảnh báo (và nó nằm trong XML cho kế hoạch). Tuyệt vời… Bây giờ tôi có thể nói chuyện với các nhà phát triển của mình về việc viết lại truy vấn này.

Sự kiện tiếp theo là cho một thống kê cột bị thiếu. Tôi đã hoàn toàn giải quyết tình huống này bằng cách tắt AUTO_CREATE_STATISTICS cho cơ sở dữ liệu AdventureWorks2014. Tôi không khuyến nghị điều này theo bất kỳ cách nào, hình dạng hoặc hình thức nào. Tùy chọn này được bật theo mặc định và tôi khuyên bạn nên luôn bật tùy chọn này. Tuy nhiên, tắt nó đi là cách dễ nhất để tạo sự kiện này. Tôi lại có truy vấn trong trường sql_text, nhưng tôi sẽ sử dụng lại plan_handle để kéo kế hoạch:

SELECT query_plan FROM sys.dm_exec_query_plan
(0x060007004448323810921C360000000001000000000000000000000000000000000000000000000000000000);

Thiếu thống kê

Và chúng tôi lại có một dấu hiệu trực quan (hình tam giác màu vàng với dấu chấm than) để chỉ ra rằng có vấn đề với kế hoạch và lại là vấn đề trong XML. Từ đây, trước tiên, tôi sẽ kiểm tra xem AUTO_CREATE_STATISTICS có bị tắt hay không, và nếu không, tôi sẽ bắt đầu chạy truy vấn trong Management Studio để xem liệu tôi có thể tạo lại cảnh báo hay không (và buộc tạo thống kê).

Giờ đây, các sự kiện còn lại thú vị hơn một chút.

Bạn sẽ nhận thấy rằng chúng ta có ba sự kiện chưa được khớp_filtered_indexes. Tôi vẫn chưa xác định lý do tại sao, nhưng tôi đang làm việc với nó và sẽ đăng trong phần nhận xét nếu / khi tôi sắp xếp nó. Hiện tại, tôi có sự kiện là đủ và trong sự kiện, chúng tôi cũng có thể xem thông tin đối tượng để tôi biết chỉ mục được đề cập:

Chỉ mục NCI_SalesOrderHeader được tham chiếu bởi sự kiện chỉ mục bị thiếu

Và tôi lại có thể lấy plan_handle để tìm kế hoạch truy vấn:

Chỉ số chưa từng có

Lần này, tôi thấy cảnh báo trong toán tử CHỌN, vì vậy tôi biết có điều gì đó tôi cần phải điều tra thêm. Trong trường hợp này, bạn có các tùy chọn để yêu cầu trình tối ưu hóa sử dụng chỉ mục đã lọc khi bạn đang sử dụng các tham số và tôi khuyên bạn nên xem qua bài đăng của Aaron để biết thêm thông tin về cách sử dụng chỉ mục đã lọc.

Cuối cùng, chúng tôi có chín sự kiện cho plan_affecting_convert. Cái quái gì vậy? Tôi vẫn đang tìm hiểu vấn đề này, nhưng tôi đã sử dụng tùy chọn Theo dõi Nhân quả cho phiên sự kiện của mình (khi thử nghiệm) để xác nhận rằng tất cả các sự kiện đều là một phần của cùng một nhiệm vụ (chúng đúng như vậy). Nếu bạn nhìn vào phần tử biểu thức trong đầu ra, bạn thấy rằng nó thay đổi một chút (cũng như compile_time) và điều này hiển thị khi bạn xem chi tiết cảnh báo trong SQL Sentry’s Plan Explorer (xem ảnh chụp màn hình thứ hai bên dưới). Trong đầu ra sự kiện, phần tử biểu thức does cho chúng tôi biết cột nào có liên quan, cột nào mới bắt đầu nhưng gần như không đủ thông tin, vì vậy, một lần nữa chúng tôi cần bắt đầu lập kế hoạch:

SELECT query_plan FROM sys.dm_exec_query_plan
(0x0600070023747010E09E1C360000000001000000000000000000000000000000000000000000000000000000);

Kế hoạch ảnh hưởng đến chuyển đổi

Chi tiết chuyển đổi từ kế hoạch

Chúng ta lại thấy người bạn của mình, hình tam giác màu vàng, trong toán tử SELECT, và trong XML, chúng ta có thể tìm thấy thuộc tính PlanAffectingConvert. Thuộc tính này đã được thêm vào lược đồ chương trình SQL Server 2012, vì vậy nếu đang chạy phiên bản cũ hơn, bạn sẽ không thấy thuộc tính này trong kế hoạch. Việc giải quyết cảnh báo này có thể đòi hỏi nhiều công việc hơn một chút - bạn cần hiểu nơi mình gặp phải sự không khớp về loại dữ liệu và lý do, sau đó bắt đầu sửa đổi mã hoặc giản đồ… cả hai đều có thể gặp phải sự phản kháng. Jonathan có một bài đăng thảo luận chi tiết hơn về chuyển đổi ngầm, đây là một nơi tốt để bắt đầu nếu bạn chưa làm việc với các vấn đề chuyển đổi trước đây.

Tóm tắt

Thư viện Sự kiện mở rộng gồm các sự kiện tiếp tục phát triển và một điều cần xem xét khi khắc phục sự cố trong SQL Server là liệu bạn có thể lấy thông tin mình đang tìm kiếm theo cách khác hay không. Có lẽ vì nó dễ dàng hơn (tôi chắc chắn thích XE hơn XML!), Hoặc vì nó hiệu quả hơn hoặc cung cấp cho bạn nhiều chi tiết hơn. Cho dù bạn đang chủ động tìm kiếm các vấn đề truy vấn trong môi trường của mình hoặc phản ứng với vấn đề mà ai đó đã báo cáo nhưng bạn đang gặp sự cố khi tìm ra nó, thì các sự kiện mở rộng là một lựa chọn khả thi để xem xét, đặc biệt khi nhiều tính năng mới được thêm vào SQL Server.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Các kế hoạch khác nhau cho các máy chủ giống hệt nhau

  2. Chốt APPEND_ONLY_STORAGE_INSERT_POINT

  3. Mô hình dữ liệu tổ chức đám cưới

  4. Ký hiệu ERD trong mô hình hóa dữ liệu

  5. Lược đồ Switch-A-Roo:Phần 2