Một trong những cải tiến kế hoạch thực thi trong SQL Server 2012 là việc bổ sung thông tin sử dụng và đặt trước luồng cho các kế hoạch thực thi song song. Bài đăng này xem xét chính xác ý nghĩa của những con số này và cung cấp thêm thông tin chi tiết để hiểu về thực thi song song.
Hãy xem xét truy vấn sau chạy trên phiên bản mở rộng của cơ sở dữ liệu AdventureWorks:
SELECT BP.ProductID, cnt = COUNT_BIG(*) FROM dbo.bigProduct AS BP JOIN dbo.bigTransactionHistory AS BTH ON BTH.ProductID = BP.ProductID GROUP BY BP.ProductID ORDER BY BP.ProductID;
Trình tối ưu hóa truy vấn chọn một kế hoạch thực thi song song:
Plan Explorer hiển thị chi tiết sử dụng luồng song song trong chú giải công cụ nút gốc. Để xem thông tin tương tự trong SSMS, hãy nhấp vào nút gốc của kế hoạch, mở cửa sổ Thuộc tính và mở rộng ThreadStat nút. Sử dụng máy có tám bộ xử lý logic có sẵn cho SQL Server để sử dụng, thông tin sử dụng luồng từ một lần chạy điển hình của truy vấn này được hiển thị bên dưới, Plan Explorer ở bên trái, chế độ xem SSMS ở bên phải:
Ảnh chụp màn hình cho thấy công cụ thực thi dành riêng 24 luồng cho truy vấn này và kết thúc bằng 16 luồng trong số đó. Nó cũng cho thấy rằng kế hoạch truy vấn có ba nhánh , mặc dù nó không nói chính xác chi nhánh là gì. Nếu bạn đã đọc bài viết Simple Talk của tôi về thực thi truy vấn song song, bạn sẽ biết rằng các nhánh là các phần của kế hoạch truy vấn song song được giới hạn bởi các toán tử trao đổi. Sơ đồ dưới đây vẽ các ranh giới và đánh số các nhánh (bấm để phóng to):
Nhánh Hai (Màu cam)
Trước tiên, hãy xem xét nhánh hai chi tiết hơn một chút:
Ở mức độ song song (DOP) là tám, có tám luồng chạy nhánh này của kế hoạch truy vấn. Điều quan trọng là phải hiểu rằng đây là toàn bộ kế hoạch thực hiện liên quan đến tám chủ đề này - họ không có kiến thức về kế hoạch rộng lớn hơn.
Trong kế hoạch thực thi nối tiếp, một chuỗi đơn đọc dữ liệu từ nguồn dữ liệu, xử lý các hàng thông qua một số toán tử kế hoạch và trả về kết quả đến đích (ví dụ:có thể là cửa sổ kết quả truy vấn SSMS hoặc bảng cơ sở dữ liệu).
Trong một chi nhánh của một kế hoạch thực thi song song, tình huống rất giống nhau:mỗi luồng đọc dữ liệu từ một nguồn, xử lý các hàng thông qua một số toán tử kế hoạch và trả kết quả đến đích. Sự khác biệt là đích đến là một toán tử trao đổi (song song) và nguồn dữ liệu cũng có thể là một trao đổi.
Trong nhánh màu cam, nguồn dữ liệu là Quét chỉ mục theo cụm và đích là phía bên phải của trao đổi Luồng phân vùng lại. Phía bên phải của trao đổi được gọi là phía nhà sản xuất , bởi vì nó kết nối với một chi nhánh bổ sung dữ liệu vào sàn giao dịch.
Tám luồng trong nhánh màu cam hợp tác để quét bảng và thêm hàng vào trao đổi. Trao đổi tập hợp các hàng thành các gói có kích thước trang. Khi một gói tin đầy, nó sẽ được đẩy qua sàn giao dịch sang phía bên kia. Nếu trao đổi có sẵn một gói trống khác để lấp đầy, quá trình tiếp tục cho đến khi tất cả các hàng nguồn dữ liệu được xử lý (hoặc trao đổi hết gói trống).
Chúng tôi có thể xem số hàng được xử lý trên mỗi luồng bằng cách sử dụng dạng xem Cây kế hoạch trong Trình khám phá kế hoạch:
Plan Explorer giúp bạn dễ dàng xem cách các hàng được phân phối trên các chuỗi cho tất cả các hoạt động vật lý trong kế hoạch. Trong SSMS, bạn bị giới hạn trong việc xem phân phối hàng cho một nhà khai thác gói duy nhất. Để thực hiện việc này, hãy bấm vào biểu tượng toán tử, mở cửa sổ Thuộc tính, sau đó mở rộng nút Số hàng Thực tế. Hình bên dưới hiển thị thông tin SSMS cho nút Luồng phân vùng lại ở biên giới giữa các nhánh màu cam và màu tím:
Nhánh 3 (Xanh lục)
Nhánh ba tương tự như nhánh hai, nhưng nó chứa thêm toán tử Tổng hợp Dòng. Cành màu xanh lá cây cũng có tám sợi, tổng cộng có mười sáu sợi được nhìn thấy cho đến nay. Tám luồng nhánh màu xanh lá cây đọc dữ liệu từ Quét chỉ mục không phân tán, thực hiện một số loại tổng hợp và chuyển kết quả cho phía nhà sản xuất của một cuộc trao đổi Luồng phân vùng khác.
Chú giải công cụ Plan Explorer cho Tổng hợp luồng cho thấy nó đang nhóm theo ID sản phẩm và tính toán một biểu thức có nhãn partialagg1005
:
Tab Biểu thức hiển thị biểu thức là kết quả của việc đếm các hàng trong mỗi nhóm:
Tổng hợp Luồng đang tính toán một phần (còn được gọi là 'địa phương') tổng hợp. Bộ định lượng một phần (hoặc cục bộ) chỉ đơn giản có nghĩa là mỗi luồng tính tổng hợp trên các hàng mà nó nhìn thấy. Các hàng từ Quét chỉ mục được phân phối giữa các luồng bằng cách sử dụng lược đồ dựa trên nhu cầu:không có sự phân phối cố định của các hàng trước thời hạn; các chủ đề nhận được một loạt các hàng từ quá trình quét khi chúng yêu cầu chúng. Những hàng nào kết thúc trên chuỗi nào về cơ bản là ngẫu nhiên vì nó phụ thuộc vào vấn đề thời gian và các yếu tố khác.
Mỗi chuỗi nhìn thấy các hàng khác nhau từ quá trình quét, trừ các hàng có cùng ID sản phẩm có thể được nhìn thấy bởi nhiều hơn một chủ đề. Tổng hợp là 'một phần' vì tổng phụ cho một nhóm ID sản phẩm cụ thể có thể xuất hiện trên nhiều luồng; nó là 'cục bộ' vì mỗi luồng tính toán kết quả của nó chỉ dựa trên các hàng mà nó tình cờ nhận được. Ví dụ:giả sử có 1.000 hàng cho ID sản phẩm # 1 trong bảng. Một chuỗi có thể tình cờ thấy 432 trong số các hàng đó, trong khi một chuỗi khác có thể thấy 568. Cả hai chuỗi sẽ có một phần số hàng cho ID sản phẩm # 1 (432 trong một luồng, 568 trong luồng kia).
Tổng hợp một phần là cách tối ưu hóa hiệu suất vì nó làm giảm số lượng hàng sớm hơn mức có thể. Trong nhánh màu xanh lá cây, việc tổng hợp sớm dẫn đến ít hàng được tập hợp thành gói và được đẩy qua trao đổi Luồng phân vùng lại.
Nhánh 1 (Tím)
Cành tím có thêm tám sợi nữa, tính đến nay là hai mươi bốn sợi. Mỗi luồng trong nhánh này đọc các hàng từ hai trao đổi Luồng phân vùng lại và ghi các hàng vào một trao đổi Luồng tập hợp. Nhánh này có vẻ phức tạp và không quen thuộc, nhưng nó chỉ đọc các hàng từ nguồn dữ liệu và gửi kết quả đến đích, giống như bất kỳ kế hoạch truy vấn nào khác.
Phía bên phải của kế hoạch hiển thị dữ liệu được đọc từ phía bên kia của hai trao đổi Luồng phân vùng lại được nhìn thấy trong các nhánh màu cam và màu xanh lá cây. Phía (bên trái) của sàn giao dịch được gọi là người tiêu dùng bên, bởi vì các chủ đề được đính kèm ở đây đang đọc (tiêu thụ) các hàng. Tám nhánh tơ tím được người tiêu thụ dữ liệu tại hai trao đổi Luồng phân vùng lại.
Phía bên trái của cành màu tím hiển thị các hàng được viết cho nhà sản xuất của một cuộc trao đổi Gather Streams. Tám chủ đề giống nhau (đó là người tiêu dùng tại các sàn giao dịch Repartition Streams) đang thực hiện nhà sản xuất vai trò ở đây.
Mỗi luồng trong nhánh màu tím chạy mọi toán tử trong nhánh, giống như một luồng duy nhất thực hiện mọi hoạt động trong một kế hoạch thực thi nối tiếp. Sự khác biệt chính là có tám luồng chạy đồng thời, mỗi luồng làm việc trên một hàng khác nhau tại bất kỳ thời điểm nhất định nào, sử dụng các phiên bản khác nhau của toán tử kế hoạch truy vấn.
Tổng hợp Luồng trong nhánh này là toàn cầu tổng hợp. Nó kết hợp các tổng hợp một phần (cục bộ) được tính trong nhánh màu xanh lục (hãy nhớ ví dụ về số lượng 432 trong một luồng và 568 trong luồng kia) để tạo ra tổng kết hợp cho mỗi ID sản phẩm. Chú giải công cụ Plan Explorer hiển thị biểu thức kết quả toàn cục, có nhãn Expr1004:
Kết quả toàn cầu chính xác cho mỗi ID sản phẩm được tính bằng cách tính tổng các tổng từng phần, như tab Biểu thức minh họa:
Để tiếp tục ví dụ (tưởng tượng) của chúng tôi, kết quả đúng của 1.000 hàng cho ID sản phẩm # 1 sẽ nhận được bằng cách cộng hai tổng phụ là 432 và 568.
Mỗi trong số tám chuỗi nhánh màu tím đọc dữ liệu từ phía người tiêu dùng của hai trao đổi Luồng luồng, tính toán tổng hợp toàn cầu, thực hiện Kết hợp hợp nhất trên ID sản phẩm và thêm các hàng vào trao đổi Luồng tập hợp ở ngoài cùng bên trái của nhánh màu tím. Quy trình cốt lõi không khác nhiều so với một kế hoạch nối tiếp thông thường; sự khác biệt nằm ở vị trí các hàng được đọc từ đâu, chúng được gửi đến đâu và cách các hàng được phân phối giữa các chuỗi…
Phân phối hàng trao đổi
Người đọc cảnh báo sẽ tự hỏi về một vài chi tiết vào thời điểm này. Chi nhánh màu tím quản lý như thế nào để tính toán kết quả chính xác trên mỗi ID sản phẩm nhưng nhánh màu xanh lá cây thì không thể (kết quả cho cùng một ID sản phẩm được trải rộng trên nhiều chủ đề)? Ngoài ra, nếu có tám liên kết hợp nhất riêng biệt (một liên kết cho mỗi chủ đề) thì SQL Server đảm bảo rằng các hàng sẽ tham gia kết thúc tại cùng một phiên bản như thế nào tham gia?
Cả hai câu hỏi này đều có thể được trả lời bằng cách xem xét cách hai Luồng phân vùng trao đổi định tuyến các hàng từ phía nhà sản xuất (trong nhánh màu xanh lá cây và màu cam) đến phía người tiêu dùng (trong nhánh màu tím). Trước tiên, chúng ta sẽ xem xét sự trao đổi Dòng phân vùng bao gồm các nhánh màu cam và màu tím:
Trao đổi này định tuyến các hàng đến (từ nhánh màu cam) bằng cách sử dụng hàm băm được áp dụng cho cột ID sản phẩm. Kết quả là tất cả các hàng cho một ID sản phẩm cụ thể đều được đảm bảo được chuyển đến cùng một sợi nhánh màu tím. Các chủ đề màu cam và màu tím không biết gì về quá trình định tuyến này; tất cả điều này được xử lý nội bộ bởi sàn giao dịch.
Tất cả các luồng màu cam biết là chúng đang trả về các hàng cho trình vòng lặp chính đã yêu cầu chúng (phía nhà sản xuất của trao đổi). Tương tự, tất cả các luồng màu tím 'biết' là chúng đang đọc các hàng từ một nguồn dữ liệu. Trao đổi xác định gói nào mà một hàng luồng màu cam đến sẽ đi vào và nó có thể là bất kỳ một trong tám gói ứng viên. Tương tự, trao đổi xác định gói nào sẽ đọc một hàng để đáp ứng yêu cầu đọc từ một chuỗi màu tím.
Hãy cẩn thận để không có được hình ảnh tinh thần về một sợi (nhà sản xuất) màu cam cụ thể được liên kết trực tiếp với một sợi màu tím (người tiêu dùng) cụ thể. Đó không phải là cách kế hoạch truy vấn này hoạt động. Một nhà sản xuất cam may kết thúc việc gửi các hàng đến tất cả người tiêu dùng màu tím - việc định tuyến hoàn toàn phụ thuộc vào giá trị của cột ID sản phẩm trong mỗi hàng mà nó xử lý.
Cũng lưu ý rằng một gói hàng tại sàn giao dịch chỉ được chuyển khi nó đã đầy (hoặc khi phía nhà sản xuất hết dữ liệu). Hãy tưởng tượng sự trao đổi lấp đầy các gói một hàng tại một thời điểm, trong đó các hàng cho một gói cụ thể có thể đến từ bất kỳ luồng nào phía nhà sản xuất (màu cam). Sau khi một gói đầy, nó sẽ được chuyển đến phía người tiêu dùng, nơi một người tiêu dùng cụ thể (màu tím) có thể bắt đầu đọc từ đó.
Trao đổi Repartition Streams bao quanh các nhánh màu xanh lá cây và màu tím hoạt động theo cách rất giống nhau:
Các hàng được chuyển đến các gói trong trao đổi này bằng cách sử dụng cùng một hàm băm trên cùng một cột phân vùng như đối với trao đổi màu cam-tím đã thấy trước đây. Điều này có nghĩa là cả hai Luồng phân vùng lại trao đổi các hàng định tuyến có cùng ID sản phẩm với cùng một chuỗi nhánh màu tím.
Điều này giải thích cách Tổng hợp luồng trong nhánh màu tím có thể tính toán tổng hợp toàn cầu - nếu một hàng có ID sản phẩm cụ thể được nhìn thấy trên một chuỗi nhánh màu tím cụ thể, thì luồng đó được đảm bảo xem tất cả các hàng cho ID sản phẩm đó (và không luồng khác sẽ).
Cột phân vùng trao đổi chung cũng là khóa tham gia cho phép kết hợp, vì vậy tất cả các hàng có thể tham gia đều được đảm bảo sẽ được xử lý bởi cùng một chuỗi (màu tím).
Một điều cuối cùng cần lưu ý là cả hai sàn giao dịch đều duy trì trật tự (a.k.a 'hợp nhất') trao đổi, như được hiển thị trong thuộc tính Order By trong chú giải công cụ. Điều này đáp ứng yêu cầu liên kết hợp nhất mà các hàng đầu vào được sắp xếp trên các khóa kết hợp. Lưu ý rằng các sàn giao dịch không bao giờ tự sắp xếp các hàng, chúng chỉ có thể được định cấu hình để giữ nguyên đơn đặt hàng hiện có.
Thread Zero
Phần cuối cùng của kế hoạch thực hiện nằm ở bên trái của sàn giao dịch Gather Streams. Nó luôn chạy trên một luồng duy nhất - cùng một luồng được sử dụng để chạy toàn bộ kế hoạch nối tiếp thông thường. Luồng này luôn được gắn nhãn 'Luồng 0' trong các kế hoạch thực thi và đôi khi được gọi là luồng 'điều phối viên' (một chỉ định mà tôi không thấy đặc biệt hữu ích).
Luồng số không đọc các hàng từ phía người tiêu dùng (bên trái) của trao đổi Gather Streams và trả chúng cho máy khách. Không có trình vòng lặp không luồng nào ngoài trao đổi trong ví dụ này, nhưng nếu có, tất cả chúng sẽ chạy trên cùng một luồng duy nhất. Lưu ý rằng Gather Streams cũng là một trao đổi hợp nhất (nó có thuộc tính Order By):
Các kế hoạch song song phức tạp hơn có thể bao gồm các khu vực thực thi nối tiếp khác với khu vực bên trái của trao đổi Gather Streams cuối cùng. Các vùng nối tiếp này không chạy trong chuỗi không, nhưng đó là một chi tiết để khám phá vào lúc khác.
Các chủ đề đã lưu trữ và đã sử dụng được xem lại
Chúng ta đã thấy rằng kế hoạch song song này có ba nhánh. Điều này giải thích tại sao SQL Server dành riêng 24 chủ đề (ba nhánh tại DOP 8). Câu hỏi đặt ra là tại sao chỉ có 16 chủ đề được báo cáo là 'được sử dụng' trong ảnh chụp màn hình ở trên.
Có hai phần cho câu trả lời. Phần đầu tiên không áp dụng cho kế hoạch này, nhưng điều quan trọng là phải biết về nó. Số nhánh được báo cáo là số lượng tối đa có thể thực hiện đồng thời .
Như bạn có thể biết, một số nhà khai thác kế hoạch nhất định đang 'chặn' - nghĩa là họ phải tiêu thụ tất cả các hàng đầu vào của mình trước khi có thể tạo ra hàng đầu ra đầu tiên. Ví dụ rõ ràng nhất về toán tử chặn (còn được gọi là dừng và đi) là Sắp xếp. Một sắp xếp không thể trả về hàng đầu tiên trong trình tự đã sắp xếp trước khi nó nhìn thấy mọi hàng đầu vào vì hàng đầu vào cuối cùng có thể sắp xếp đầu tiên.
Các toán tử có nhiều đầu vào (ví dụ:liên kết và liên kết) có thể chặn đối với một đầu vào, nhưng không chặn ('pipelined') đối với đầu vào kia. Một ví dụ về điều này là tham gia băm - đầu vào xây dựng đang bị chặn, nhưng đầu vào thăm dò là pipelined. Đầu vào bản dựng đang bị chặn vì nó tạo bảng băm dựa vào đó các hàng thăm dò được kiểm tra.
Sự hiện diện của các toán tử chặn có nghĩa là một hoặc nhiều nhánh song song có thể được đảm bảo hoàn thành trước khi những người khác có thể bắt đầu. Khi điều này xảy ra, SQL Server có thể tái sử dụng các luồng được sử dụng để xử lý một nhánh đã hoàn thành cho một nhánh sau đó trong chuỗi. SQL Server rất thận trọng về đặt trước luồng, vì vậy chỉ các nhánh được đảm bảo để hoàn thành trước khi bắt đầu khác, hãy sử dụng tối ưu hóa đặt trước chuỗi này. Kế hoạch truy vấn của chúng tôi không chứa bất kỳ toán tử chặn nào, vì vậy số nhánh được báo cáo chỉ là tổng số nhánh.
Phần thứ hai của câu trả lời là các chuỗi vẫn có thể được sử dụng lại nếu chúng xảy ra để hoàn thành trước khi một luồng trong nhánh khác bắt đầu. Số lượng chủ đề đầy đủ vẫn được bảo lưu trong trường hợp này, nhưng mức sử dụng thực tế có thể thấp hơn. Một gói song song thực sự sử dụng bao nhiêu luồng phụ thuộc vào các vấn đề về thời gian trong số những thứ khác và có thể khác nhau giữa các lần thực thi.
Các luồng song song không phải tất cả đều bắt đầu thực hiện cùng một lúc, nhưng một lần nữa, chi tiết về điều đó sẽ phải đợi một dịp khác. Hãy xem lại kế hoạch truy vấn để xem các luồng có thể được sử dụng lại như thế nào, mặc dù thiếu các toán tử chặn:
Rõ ràng là các luồng trong nhánh một không thể hoàn thành trước khi các luồng trong nhánh hai hoặc ba khởi động, vì vậy sẽ không có cơ hội sử dụng lại luồng ở đó. Nhánh ba cũng không có khả năng xảy ra hoàn thành trước khi nhánh một hoặc nhánh hai bắt đầu vì nó có quá nhiều việc phải làm (cần tổng hợp gần 32 triệu hàng).
Nhánh hai là một vấn đề khác. Kích thước tương đối nhỏ của bảng sản phẩm có nghĩa là có nhiều khả năng chi nhánh có thể hoàn thành công việc của mình trước nhánh ba khởi động. Nếu việc đọc bảng sản phẩm không dẫn đến bất kỳ I / O vật lý nào, thì sẽ không mất nhiều thời gian cho tám luồng để đọc 25.200 hàng và gửi chúng đến trao đổi Luồng tái phân vùng ranh giới màu cam-tím.
Đây chính xác là những gì đã xảy ra trong các lần chạy thử nghiệm được sử dụng cho các ảnh chụp màn hình được thấy cho đến nay trong bài đăng này:tám luồng nhánh màu cam hoàn thành đủ nhanh để chúng có thể được sử dụng lại cho nhánh màu xanh lá cây. Tổng cộng, mười sáu luồng duy nhất đã được sử dụng, do đó, đó là những gì kế hoạch thực thi báo cáo.
Nếu truy vấn được chạy lại với bộ đệm lạnh, độ trễ do I / O vật lý đưa vào là đủ để đảm bảo rằng các luồng nhánh màu xanh lá cây khởi động trước khi bất kỳ luồng nhánh màu cam nào hoàn thành. Không có luồng nào được sử dụng lại, vì vậy kế hoạch thực thi báo cáo rằng tất cả 24 luồng dự trữ trên thực tế đã được sử dụng:
Nói chung hơn, có thể có bất kỳ số 'chuỗi đã sử dụng' nào giữa hai cực trị (16 và 24 cho kế hoạch truy vấn này):
Cuối cùng, xin lưu ý rằng chuỗi chạy phần nối tiếp của kế hoạch ở bên trái Luồng tập hợp cuối cùng không được tính trong tổng số chủ đề song song. Nó không phải là một chuỗi bổ sung được thêm vào để hỗ trợ thực thi song song.
Lời kết
Vẻ đẹp của mô hình trao đổi được SQL Server sử dụng để triển khai thực thi song song là tất cả sự phức tạp của việc đệm và di chuyển các hàng giữa các luồng đều được ẩn bên trong các toán tử trao đổi (Parallelism). Phần còn lại của kế hoạch được chia thành các 'nhánh' gọn gàng, được ràng buộc bởi các sàn giao dịch. Trong một nhánh, mỗi nhà khai thác hoạt động giống như trong một kế hoạch nối tiếp - trong hầu hết các trường hợp, các nhà khai thác nhánh không biết rằng gói rộng hơn sử dụng thực thi song song.
Chìa khóa để hiểu về thực thi song song là (về mặt tinh thần) phá vỡ kế hoạch song song ở các ranh giới trao đổi và hình dung mỗi nhánh như DOP nối tiếp riêng biệt kế hoạch, tất cả thực thi đồng thời trên một tập hợp con riêng biệt của các hàng. Đặc biệt nhớ rằng mỗi gói nối tiếp như vậy chạy tất cả các toán tử trong nhánh đó - SQL Server không chạy từng toán tử trên chuỗi của riêng nó!
Để hiểu được hành vi chi tiết nhất đòi hỏi một chút suy nghĩ, đặc biệt là về cách các hàng được định tuyến trong các trao đổi và cách công cụ đảm bảo kết quả chính xác, nhưng sau đó hầu hết những thứ đáng biết đều cần một chút suy nghĩ, phải không?