Bạn có thể giải quyết vấn đề này mà không cần tham gia, có nghĩa là nó sẽ có hiệu suất tốt hơn. Ý tưởng là nhóm dữ liệu theo object_id của bạn, đếm số hàng của mỗi object_id. Đây là những gì "phân vùng theo" làm. Sau đó, bạn có thể cập nhật nơi row_num> 1. Điều này sẽ cập nhật tất cả object_id trùng lặp ngoại trừ cái đầu tiên!
update t set t.status_val = 'some_status'
from (
select *, row_number() over(partition by object_id order by (select null)) row_num
from foo
) t
where row_num > 1
Trên bảng kiểm tra gồm 82944 bản ghi, hiệu suất là như vậy (số dặm của bạn có thể thay đổi!):Bảng 'kiểm tra'. Quét đếm 5, đọc logic 82283, đọc vật lý 0, đọc trước đọc 0, đọc logic lob 0, đọc vật lý lob 0, đọc trước lob 0, thời gian đọc trước 0,CPU =141 ms, thời gian trôi qua =150 ms.
Chúng tôi chắc chắn cũng có thể giải quyết vấn đề này bằng cách sử dụng kết nối bên trong, tuy nhiên, nói chung điều này sẽ dẫn đến việc đọc logic hơn và CPU cao hơn:
Bảng 'kiểm tra'. Số lần quét 10, đọc logic 83622, đọc vật lý 0, đọc trước đọc 0, đọc logic lob 0, đọc vật lý lob 0, đọc trước lob đọc 0. Bảng 'Workfile'. Quét đếm 0, đọc lôgic 0, đọc vật lý 0, đọc trước đọc 0, đọc lôgic 0, ghi lôgic vật lý 0, đọc trước lôgic đọc 0. Bảng 'Bàn làm việc'. Quét đếm 4, đọc logic 167426, đọc vật lý 0, đọc trước đọc 0, đọc logic lob 0, đọc vật lý lob 0, đọc trước lob 0, thời gian đọc trước 0,CPU =342 mili giây, thời gian trôi qua =233 mili giây.
Để lặp lại các kết quả và cập nhật trong các đợt nhỏ hơn:
declare @rowcount int = 1;
declare @batch_size int = 1000;
while @rowcount > 0
begin
update top(@batch_size) t set t.status_val = 'already updated'
from (
select *, row_number() over(partition by object_id order by (select null)) row_num
from foo
where status_val <> 'already updated'
) t
where row_num > 1
set @rowcount = @@rowcount;
end
Điều này sẽ giúp tiếp tục khóa nếu các phiên đồng thời khác đang cố gắng truy cập bảng này.