sql >> Databasteknik >  >> RDS >> Sqlserver

Uppdatera alla utom en av dubbletter i tabellen i SQL Server

Du kan lösa det här problemet utan en join, vilket betyder att det borde ha bättre prestanda. Tanken är att gruppera data efter ditt object_id, och räkna radnumret för varje object_id. Detta är vad "partition by" gör. Sedan kan du uppdatera var row_num är> 1. Detta kommer att uppdatera alla duplicerade object_id utom det första!

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 

På en testtabell med 82944 poster var prestandan sådan (din körsträcka kan variera!):Tabell 'test'. Skanningsantal 5, logiskt läser 82283, fysiskt läser 0, read-ahead läser 0, lob logiskt läser 0, lob fysisk läser 0, lob läser framåt läser 0. CPU-tid =141 ms, förfluten tid =150 ms.

Vi kan säkert också lösa detta problem genom att använda en inre koppling, men i allmänhet borde detta leda till mer logiska läsningar och högre CPU:

Tabell 'test'. Scan count 10, logiskt läser 83622, fysiskt läser 0, read-ahead läser 0, lob logiskt läser 0, lob fysisk läser 0, lob läser framåt läser 0. Tabell 'Arbetsfil'. Scan count 0, logiskt läser 0, fysiskt läser 0, read-ahead läser 0, lob logiskt läser 0, lob fysisk läser 0, lob read-ahead läser 0. Tabell 'Arbetstabell'. Scan count 4, logiskt läser 167426, fysiskt läser 0, read-ahead läser 0, lob logiskt läser 0, lob fysisk läser 0, lob läser framåt läser 0. CPU-tid =342 ms, förfluten tid =233 ms.

Så här går du igenom resultaten och uppdaterar i mindre omgångar:

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

Detta hjälper till att fortsätta låsa om andra samtidiga sessioner försöker komma åt den här tabellen.



  1. Konvertera ett objekt till en sträng i PHP

  2. Långsamma MySQL-inlägg

  3. Jämförelse av Oracle UCP, C3P0 och HikariCP

  4. SQL Server OM INTE FINNS Användning?