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.
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('');
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ờ:
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())]');
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. –
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? –
@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