2015-05-04 14 views
6

Trong SQL Server, tôi có một thủ tục lưu sẵn với biến kiểu XML tạm thời, và tôi đang thực hiện thao tác xóa trên biến đó. Khi tôi đang chạy thủ tục này được lưu trữ trong máy ảo địa phương của tôi trong đó có 4 lõi và 6 GB RAM, phải mất 24 giây để thực thi. Nhưng khi tôi đang chạy cùng một thủ tục lưu trữ trong máy chủ với 40 lõi và RAM 128 GB, lệnh xóa này mất hơn 38 phút để thực thi. Toàn bộ thủ tục lưu trữ bị treo tại lệnh xóa này trong 38 phút. Sau khi bình luận ra câu lệnh xóa, thủ tục được lưu trữ sẽ thực hiện trong 8 giây trên máy chủ. Làm thế nào tôi có thể khắc phục vấn đề hiệu suất này. Có điều gì sai trong cấu hình máy chủ SQL không?Trong SQL Server, xóa các nút bằng cách sử dụng .modify() XQuery dùng 38 phút để thực hiện

DECLARE @PaymentData AS XML 

SET @PaymentData = .....(Main XML Query) 

SET @PaymentData.modify('delete //*[not(node())]') 

@Mikael: Dưới đây là kế hoạch thực hiện cho việc băm nhỏ thành hàng giải pháp trên máy chủ (với 40 lõi và 128 GB RAM) enter image description here enter image description here Và Dưới đây là kế hoạch excecution trong VM địa phương của tôi (với 4 lõi và 6 GB RAM): enter image description here enter image description here

+0

Nếu lượng dữ liệu trong cả hai trường hợp có thể so sánh, bạn có thể thử 'tùy chọn (maxdop)' để giảm mức độ song song. –

+1

Bạn đang sử dụng phiên bản SQL Server nào? Chúng có giống nhau trên cả hai máy chủ không? Kích thước và nội dung của XML có giống nhau không? Các kế hoạch truy vấn có giống nhau không? –

+0

@RogerWolf Tôi đã thử thêm tùy chọn (maxdop 1) vào truy vấn, nhưng hiệu suất tương tự của nó – Rakesh

Trả lời

7

Trên máy tính của tôi xóa mất 1 giờ 25 phút và đã cho tôi kế hoạch truy vấn không quá xinh đẹp này.

enter image description here

kế hoạch này sẽ giúp tìm tất cả các nút rỗng (những người bị xóa) và các cửa hàng những người trong một ống chỉ Table. Sau đó, cho mỗi nút trong toàn bộ tài liệu có một kiểm tra nếu nút đó có mặt trong spool (Nested Loops (Left Semi Join)) và nếu nó là nút được loại trừ khỏi kết quả cuối cùng (Merge join (Left Anti Semi Join)). Sau đó, xml được xây dựng lại từ các nút trong toán tử UDX và gán cho biến đó. Các spool bảng không được lập chỉ mục như vậy cho mỗi nút cần được kiểm tra sẽ có một quét của toàn bộ ống chỉ (hoặc cho đến khi một kết hợp được tìm thấy).

Điều đó có nghĩa là hiệu suất của thuật toán này là O(n*d) trong đó n là tổng số nút và d là tổng số hoặc các nút đã xóa.

Có một vài cách giải quyết có thể xảy ra.

Đầu tiên và có lẽ tốt nhất là nếu bạn có thể sửa đổi truy vấn XML của mình để không tạo ra các nút trống ở vị trí đầu tiên. Hoàn toàn có thể nếu bạn tạo XML với for xml và có lẽ không thể nếu bạn đã có các phần của XML được lưu trữ trong một bảng.

Một tùy chọn khác là băm nhỏ XML trên (xem XML mẫu bên dưới), đặt kết quả trong biến bảng, sửa đổi XML trong biến bảng và sau đó tạo lại XML kết hợp.

declare @T table(PaymentData xml); 

insert into @T 
select T.X.query('.') 
from @PaymentData.nodes('Row') as T(X); 

update @T 
set PaymentData.modify('delete //*[not(node())]'); 

select T.PaymentData as '*' 
from @T as T 
for xml path(''); 

enter image description here

này sẽ cung cấp cho bạn các tính năng của O(n*s*d) nơi n là số row nút, s là số sub-node mỗi row nút và d được số hàng bị xóa mỗi row nút.

Tùy chọn thứ ba mà tôi thực sự không thể đề xuất là sử dụng cờ theo dõi không có giấy tờ để loại bỏ việc sử dụng ống chỉ trong kế hoạch. Bạn có thể thử nó trong thử nghiệm hoặc bạn có lẽ có thể nắm bắt kế hoạch được tạo ra và sử dụng nó trong một hướng dẫn kế hoạch.

declare @T table(PaymentData xml); 

insert into @T values(@PaymentData); 

update @T 
set PaymentData.modify('delete //*[not(node())]') 
option (querytraceon 8690); 

select @PaymentData = PaymentData 
from @T; 

kế hoạch truy vấn với dấu vết cờ:

enter image description here

Thay vào đó là 1 giờ 25 phút, phiên bản này mất 4 giây trên máy tính của tôi.

Việc băm nhỏ XML thành nhiều hàng thành biến bảng mất tổng cộng 6 giây để thực thi.

Không phải xóa bất kỳ hàng nào cả, tất nhiên là nhanh nhất.

Dữ liệu mẫu, 12.000 nút với 32 phân đoạn nơi 2 ô trống nếu bạn muốn dùng thử tại nhà.

declare @PaymentData as xml; 

set @PaymentData = (
        select top(12000) 
        1 as N1, 1 as N2, 1 as N3, 1 as N4, 1 as N5, 1 as N6, 1 as N7, 1 as N8, 1 as N9, 1 as N10, 
        1 as N11, 1 as N12, 1 as N13, 1 as N14, 1 as N15, 1 as N16, 1 as N17, 1 as N18, 1 as N19, 1 as N20, 
        1 as N21, 1 as N22, 1 as N23, 1 as N24, 1 as N25, 1 as N26, 1 as N27, 1 as N28, 1 as N29, 1 as N30, 
        '' as N31, 
        '' as N32 
        from sys.columns as c1, sys.columns as c2 
        for xml path('Row') 
        ); 

Lưu ý: Tôi không biết tại sao chỉ mất 24 giây để thực thi trên một trong các máy chủ của bạn. Tôi khuyên bạn nên kiểm tra lại xem XML có thực sự giống hệt hay không. Hoặc tại sao không thử nghiệm bằng cách sử dụng mẫu XML mà tôi đã cung cấp cho bạn.

Cập nhật:

Đối với phiên bản băm nhỏ các vấn đề với các ống chỉ trong truy vấn xóa có thể được chuyển đến các truy vấn băm nhỏ thay vì để lại cho bạn về việc thực hiện xấu như vậy. Tuy nhiên đó không phải lúc nào cũng đúng. Tôi đã thấy những kế hoạch không có ống và kế hoạch nơi có một ống chỉ và tôi không biết tại sao nó có đôi khi và tại sao nó không phải vào những lúc khác.

Tôi cũng thấy rằng nếu bạn sử dụng bảng tạm thời thay vì insert ... into Tôi không nhận được ống chỉ trong truy vấn băm nhỏ.

select T.X.query('.') as PaymentData 
into #T 
from @PaymentData.nodes('Row') as T(X); 

update #T 
set PaymentData.modify('delete //*[not(node())]'); 
+0

Tôi đã thử chạy các giải pháp trên với dữ liệu mẫu do bạn cung cấp, nhưng hiệu suất là như nhau. Khi tôi thử giải pháp băm nhỏ thành hàng (tổng cộng mất 1 giờ 9 giây để thực hiện), và lần này câu lệnh chèn chiếm 81% thời gian thực hiện. Và xóa tuyên bố mất 18%. Có cái gì đó sai trong cấu hình máy chủ SQL (mặc dù nó có 40 lõi và 128 GB RAM). Và tất nhiên tất cả các giải pháp của bạn đang làm việc hoàn hảo trong máy ảo cục bộ của tôi có 4 lõi và 6 GB RAM. – Rakesh

+0

@Rakesh Tôi rất muốn xem phiên bản xml của kế hoạch thực hiện thực tế từ máy ảo cục bộ nhanh của bạn cho câu lệnh gốc 'SET @ PaymentData.modify ('delete // * [not (node ​​())]')' trên dữ liệu thử nghiệm đã tạo của tôi. Bạn có thể sử dụng http://pastebin.com/ và đăng liên kết lên kế hoạch truy vấn XML ở đây trong một nhận xét hoặc bạn có thể cập nhật câu hỏi của mình bằng liên kết đến gói. Nó cũng sẽ là thú vị để xem các kế hoạch cho các giải pháp băm nhỏ tôi đã cho bạn từ cả hai máy chủ.Lưu ý: Phần trăm chi phí truy vấn không có gì liên quan đến cách truy vấn hoạt động. Họ chỉ là một ước tính ngay cả trong kế hoạch thực tế. –

+0

Tôi đã tải lên ảnh chụp màn hình của kế hoạch thực hiện bên dưới câu hỏi. – Rakesh

Các vấn đề liên quan