आप इस समस्या को बिना शामिल हुए हल कर सकते हैं, जिसका अर्थ है कि इसका प्रदर्शन बेहतर होना चाहिए। विचार प्रत्येक ऑब्जेक्ट_आईडी की पंक्ति संख्या की गणना करते हुए, अपने ऑब्जेक्ट_आईडी द्वारा डेटा को समूहित करना है। यही "विभाजन द्वारा" करता है। फिर आप अपडेट कर सकते हैं जहां row_num> 1 है। यह पहले वाले को छोड़कर सभी डुप्लिकेट किए गए ऑब्जेक्ट_आईडी को अपडेट करेगा!
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
82944 रिकॉर्ड की एक परीक्षण तालिका पर, प्रदर्शन ऐसा था (आपका लाभ भिन्न हो सकता है!):तालिका 'परीक्षण'। स्कैन काउंट 5, लॉजिकल रीड्स 82283, फिजिकल रीड्स 0, रीड-फॉरवर्ड रीड्स 0, लोब लॉजिकल रीड्स 0, लोब फिजिकल रीड्स 0, लोब रीड-आगे रीड्स 0.सीपीयू टाइम =141 एमएस, बीता हुआ समय =150 एमएस।
हम निश्चित रूप से एक आंतरिक जुड़ाव का उपयोग करके भी इस समस्या को हल कर सकते हैं, हालांकि, सामान्य तौर पर इससे अधिक तार्किक रीड और उच्च CPU होना चाहिए:
तालिका 'परीक्षण'। स्कैन काउंट 10, लॉजिकल रीड्स 83622, फिजिकल रीड्स 0, रीड-फॉरवर्ड रीड्स 0, लोब लॉजिकल रीड्स 0, लोब फिजिकल रीड्स 0, लोब रीड-आगे रीड्स 0.टेबल 'वर्कफाइल'। स्कैन काउंट 0, लॉजिकल रीड्स 0, फिजिकल रीड्स 0, रीड-फॉरवर्ड रीड्स 0, लोब लॉजिकल रीड्स 0, लोब फिजिकल रीड्स 0, लोब रीड-आगे रीड्स 0.टेबल 'वर्कटेबल'। स्कैन काउंट 4, लॉजिकल रीड्स 167426, फिजिकल रीड्स 0, रीड-फॉरवर्ड रीड्स 0, लोब लॉजिकल रीड्स 0, लोब फिजिकल रीड्स 0, लोब रीड-अहेड रीड्स 0.CPU टाइम =342 एमएस, बीता हुआ समय =233 एमएस।
परिणामों पर लूप करने और छोटे बैचों में अपडेट करने के लिए:
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
यदि अन्य समवर्ती सत्र इस तालिका तक पहुँचने का प्रयास कर रहे हैं तो यह लॉक डाउन रखने में मदद करेगा।