Tento problém můžete vyřešit bez připojení, což znamená, že by měl mít lepší výkon. Cílem je seskupit data podle vašeho object_id a počítat číslo řádku každého object_id. To je to, co dělá "partition by". Pak můžete aktualizovat, kde je row_num> 1. Tím se aktualizují všechny duplicitní object_id kromě prvního!
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
Na testovací tabulce 82944 záznamů byl výkon takový (váš počet najetých kilometrů se může lišit!):Tabulka 'test'. Počet skenů 5, logické čtení 82283, fyzické čtení 0, čtení napřed 0, logické čtení 0, fyzické čtení 0, lob čtení napřed 0. Čas CPU =141 ms, uplynulý čas =150 ms.
Tento problém můžeme jistě také vyřešit použitím vnitřního spojení, nicméně obecně by to mělo vést k logičtějšímu čtení a vyššímu CPU:
Tabulka 'test'. Počet skenů 10, logické čtení 83622, fyzické čtení 0, čtení napřed 0, logické čtení 0 lob, fyzické čtení 0, lob čtení napřed 0. Tabulka 'Workfile'. Počet skenů 0, logické čtení 0, fyzické čtení 0, čtení napřed 0, logické čtení 0 lob, fyzické čtení 0, lob čtení napřed 0. Tabulka 'Worktable'. Počet skenů 4, logické čtení 167426, fyzické čtení 0, čtení napřed 0, logické čtení 0, fyzické čtení 0, lob čtení napřed 0. Čas CPU =342 ms, uplynulý čas =233 ms.
Pro opakování výsledků a aktualizaci v menších dávkách:
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
To pomůže udržet uzamčení, pokud se jiné souběžné relace pokoušejí o přístup k této tabulce.