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

Thông tin thêm về CXPACKET Waits:Skewed Parallelism

Trong bài trước của tôi, tôi đã thảo luận về các lần chờ CXPACKET và các cách để ngăn chặn hoặc hạn chế sự song song. Tôi cũng đã giải thích cách luồng điều khiển trong một hoạt động song song luôn đăng ký CXPACKET chờ và đôi khi các luồng không phải điều khiển cũng có thể đăng ký CXPACKET chờ. Điều này có thể xảy ra nếu một trong các luồng bị chặn khi chờ tài nguyên (vì vậy tất cả các luồng khác kết thúc trước nó và đăng ký CXPACKET cũng chờ), hoặc nếu ước tính cardinality không chính xác. Trong bài đăng này, tôi muốn khám phá phần sau.

Khi ước tính số lượng không chính xác, các luồng song song thực hiện công việc truy vấn sẽ được giao một lượng công việc không đồng đều. Trường hợp điển hình là khi một luồng được giao tất cả công việc hoặc nhiều cách hoạt động hơn các luồng khác. Điều này có nghĩa là những luồng xử lý xong các hàng của chúng (nếu chúng thậm chí đã được cung cấp bất kỳ) trước khi luồng chậm nhất đăng ký một CXPACKET từ thời điểm chúng kết thúc cho đến khi luồng chậm nhất kết thúc. Sự cố này có thể dẫn đến một vụ nổ dường như xảy ra trong các lần chờ CXPACKET và thường được gọi là tính song song lệch , bởi vì sự phân bố công việc giữa các ren song song bị lệch, không đồng đều.

Lưu ý rằng trong SQL Server 2016 SP2 và SQL Server 2017 RTM CU3, các luồng khách hàng không còn đăng ký CXPACKET chờ đợi. Họ đăng ký các đợi CXCONSUMER, rất lành tính và có thể được bỏ qua. Điều này là để giảm số lượng CXPACKET chờ được tạo và những cái còn lại có nhiều khả năng có thể thực hiện được hơn.

Ví dụ về song song xiên chéo

Tôi sẽ xem qua một ví dụ có sẵn để chỉ ra cách xác định những trường hợp như vậy.

Trước hết, tôi sẽ tạo một tình huống trong đó một bảng có số liệu thống kê cực kỳ không chính xác, bằng cách đặt thủ công số hàng và số trang trong CẬP NHẬT THỐNG KÊ tuyên bố (không làm điều này trong sản xuất!):

USE [master];
GO
 
IF DB_ID (N'ExecutionMemory') IS NOT NULL
BEGIN
    ALTER DATABASE [ExecutionMemory] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
    DROP DATABASE [ExecutionMemory];
END
GO
 
CREATE DATABASE [ExecutionMemory];
GO
USE [ExecutionMemory];
GO
 
CREATE TABLE dbo.[Test] (
    [RowID] INT IDENTITY,
    [ParentID] INT,
    [CurrentValue] NVARCHAR (100),
    CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED ([RowID]));
GO
 
INSERT INTO dbo.[Test] ([ParentID], [CurrentValue])
SELECT 
    CASE WHEN ([t1].[number] % 3 = 0)
        THEN [t1].[number] – [t1].[number] % 6
        ELSE [t1].[number] END, 
    'Test' + CAST ([t1].[number] % 2 AS VARCHAR(11))
FROM [master].[dbo].[spt_values] AS [t1]
WHERE [t1].[type] = 'P';
GO
 
UPDATE STATISTICS dbo.[Test] ([PK_Test]) WITH ROWCOUNT = 10000000, PAGECOUNT = 1000000;
GO

Vì vậy, bảng của tôi chỉ có vài nghìn hàng trong đó, nhưng tôi đã giả mạo nó có 10 triệu hàng.

Bây giờ tôi sẽ tạo một truy vấn tiếp theo để chọn 500 hàng hàng đầu, các hàng này sẽ song song vì nó cho rằng có hàng triệu hàng cần quét.

USE [ExecutionMemory];
GO
 
SET NOCOUNT ON;
GO
 
DECLARE @CurrentValue NVARCHAR (100);
 
WHILE (1=1)
SELECT TOP (500) 
    @CurrentValue = [CurrentValue]
FROM dbo.[Test]
ORDER BY NEWID() DESC;
GO

Và thiết lập chạy.

Xem CXPACKET Chờ

Bây giờ tôi có thể xem các lần đợi CXPACKET đang xảy ra bằng cách sử dụng một tập lệnh đơn giản để xem xét sys.dm_os_waiting_tasks DMV:

SELECT
    [owt].[session_id],
    [owt].[exec_context_id],
    [owt].[wait_duration_ms],
    [owt].[wait_type],
    [owt].[blocking_session_id],
    [owt].[resource_description],
    [er].[database_id],
    [eqp].[query_plan]
FROM sys.dm_os_waiting_tasks [owt]
INNER JOIN sys.dm_exec_sessions [es] ON
    [owt].[session_id] = [es].[session_id]
INNER JOIN sys.dm_exec_requests [er] ON
    [es].[session_id] = [er].[session_id]
OUTER APPLY sys.dm_exec_sql_text ([er].[sql_handle]) [est]
OUTER APPLY sys.dm_exec_query_plan ([er].[plan_handle]) [eqp]
WHERE
    [es].[is_user_process] = 1
ORDER BY
    [owt].[session_id],
    [owt].[exec_context_id];

Nếu tôi thực hiện điều này một vài lần, cuối cùng tôi thấy một số kết quả hiển thị sự song song lệch (Tôi đã loại bỏ liên kết xử lý kế hoạch truy vấn và cắt bớt mô tả tài nguyên, để rõ ràng và lưu ý rằng tôi đã nhập mã để lấy văn bản SQL nếu bạn muốn điều đó quá):

session_id execute_context_id wait_duration_ms wait_type blocks_session_id resource_description database_id
56 0 1 CXPACKET NULL exchangeEvent 13
56 1 1 CXPACKET 56 exchangeEvent 13
56 3 1 CXPACKET 56 exchangeEvent 13
56 4 1 CXPACKET 56 exchangeEvent 13
56 5 1 CXPACKET 56 exchangeEvent 13
56 6 1 CXPACKET 56 exchangeEvent 13
56 7 1 CXPACKET 56 exchangeEvent 13

Kết quả hiển thị tính song song lệch trong hoạt động

Luồng điều khiển là luồng có execute_context_id được đặt thành 0. Các chuỗi song song khác là những chuỗi có execute_context_id cao hơn 0 và tất cả chúng đều hiển thị CXPACKET đang chờ ngoài một (lưu ý rằng exec_context_id = 2 bị thiếu trong danh sách). Bạn sẽ nhận thấy rằng tất cả họ đều liệt kê session_id của riêng họ là một chuỗi đang chặn họ và điều đó đúng vì tất cả các chuỗi đang chờ một chuỗi khác từ session_id của chính họ hoàn thành. database_id là cơ sở dữ liệu có ngữ cảnh mà truy vấn đang được thực thi, không nhất thiết là cơ sở dữ liệu nơi có vấn đề, nhưng thường là trừ khi truy vấn sử dụng cách đặt tên ba phần để thực thi trong một cơ sở dữ liệu khác.

Xem vấn đề ước tính bản số

Với query_plan trong đầu ra truy vấn (mà tôi đã xóa để rõ ràng), bạn có thể nhấp vào nó để hiển thị sơ đồ đồ họa và sau đó nhấp chuột phải và chọn Xem bằng SQL Sentry Plan Explorer. Điều này hiển thị như bên dưới:

Tôi có thể thấy ngay rằng có vấn đề về ước tính số lượng, vì Hàng thực tế để quét chỉ mục theo cụm chỉ là 2.048, so với 10.000.000 Hàng ước tính (ước tính).

Nếu tôi cuộn qua, tôi có thể thấy sự phân bố của các hàng trên các chuỗi song song đã được sử dụng:

Xin lưu ý, chỉ một luồng duy nhất đang thực hiện bất kỳ công việc nào trong phần song song của kế hoạch - luồng không hiển thị trong sys.dm_os_waiting_tasks sản lượng trên.

Trong trường hợp này, cách khắc phục là cập nhật số liệu thống kê cho bảng.

Trong ví dụ do tôi tạo ra, điều này sẽ không hoạt động, vì không có bất kỳ sửa đổi nào đối với bảng, vì vậy tôi sẽ chạy lại tập lệnh thiết lập, bỏ qua THỐNG KÊ CẬP NHẬT tuyên bố.

Kế hoạch truy vấn sau đó trở thành:

Trường hợp không có vấn đề về bản số và cũng không có tính song song - vấn đề đã được giải quyết!

Tóm tắt

Nếu bạn thấy CXPACKET chờ xảy ra, thì thật dễ dàng để kiểm tra xem có bị lệch song song hay không, bằng cách sử dụng phương pháp được mô tả ở trên. Tất cả các trường hợp tôi đã thấy là do các vấn đề ước tính bản số thuộc loại này hay loại khác và thường đó chỉ đơn giản là trường hợp cập nhật số liệu thống kê.

Về số liệu thống kê chờ chung có liên quan, bạn có thể tìm thêm thông tin về cách sử dụng chúng để khắc phục sự cố hiệu suất trong:

  • Loạt bài đăng trên blog SQLskills của tôi, bắt đầu với số liệu thống kê Chờ hoặc vui lòng cho tôi biết nó bị ảnh hưởng ở đâu
  • Thư viện Loại Chờ và Lớp Chốt của tôi tại đây
  • Khóa học đào tạo trực tuyến Pluralsight của tôi SQL Server:Khắc phục sự cố về hiệu suất sử dụng thống kê chờ
  • SQL Sentry

Cho đến lần sau, chúc bạn khắc phục sự cố!


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bất ngờ về hiệu suất và giả định:BẬT SỐ KHOẢN

  2. Toán tử so sánh SQL

  3. Hình ảnh thời gian chạy tùy chỉnh trong Java 9 là gì?

  4. Quan hệ vs cơ sở dữ liệu không quan hệ - Phần 3

  5. Ưu điểm của Cơ sở dữ liệu NoSQL - Mọi thứ bạn cần biết