sql >> Database >  >> RDS >> Sqlserver

Werk op één na alle dubbele records in de tabel bij in SQL Server

U kunt dit probleem oplossen zonder een join, wat betekent dat het betere prestaties zou moeten hebben. Het idee is om de gegevens te groeperen op uw object_id, waarbij het rijnummer van elke object_id wordt geteld. Dit is wat "partitioneren door" doet. Vervolgens kunt u bijwerken waar het rijnummer> 1 is. Hiermee worden alle dubbele object-id's bijgewerkt, behalve de eerste!

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 

Op een testtabel van 82944 records was de prestatie zo (je kilometerstand kan variëren!):Tabel 'test'. Scantelling 5, logische leest 82283, fysieke leest 0, read-ahead leest 0, lob logische leest 0, lob fysieke leest 0, lob read-ahead leest 0.CPU-tijd =141 ms, verstreken tijd =150 ms.

We kunnen dit probleem zeker ook oplossen door een inner join te gebruiken, maar in het algemeen zou dit moeten leiden tot meer logische reads en hogere CPU:

Tabel 'test'. Scan count 10, logische leest 83622, fysieke leest 0, read-ahead leest 0, lob logische leest 0, lob fysieke leest 0, lob read-ahead leest 0.Tabel 'Werkbestand'. Scan count 0, logische leest 0, fysieke leest 0, read-ahead leest 0, lob logische leest 0, lob fysieke leest 0, lob read-ahead leest 0. Tabel 'Werktafel'. Scantelling 4, logische leest 167426, fysieke leest 0, read-ahead leest 0, lob logische leest 0, lob fysieke leest 0, lob read-ahead leest 0.CPU-tijd =342 ms, verstreken tijd =233 ms.

Om de resultaten te herhalen en in kleinere batches bij te werken:

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

Dit zal helpen om te blijven vergrendelen als andere gelijktijdige sessies toegang proberen te krijgen tot deze tabel.



  1. NonUniqueObjectException wanneer persistent object

  2. JCombobox wordt niet weergegeven

  3. Voeg een aangepast verborgen veld toe in PayPal-vorm en krijg het op de doorverwezen pagina

  4. subquery gebruiken in plaats van de tabelnaam