J'ai besoin de supprimer des lignes en double d'une grande table. Quelle est la meilleure façon de réaliser cela?
actuellement, j'utilise cet algorithme:
declare @t table ([key] int )
insert into @t select 1
insert into @t select 1
insert into @t select 1
insert into @t select 2
insert into @t select 2
insert into @t select 3
insert into @t select 4
insert into @t select 4
insert into @t select 4
insert into @t select 4
insert into @t select 4
insert into @t select 5
insert into @t select 5
insert into @t select 5
insert into @t select 5
insert into @t select 5
insert into @t select 6
insert into @t select 6
insert into @t select 6
insert into @t select 7
insert into @t select 7
insert into @t select 8
insert into @t select 8
insert into @t select 9
insert into @t select 9
insert into @t select 9
insert into @t select 9
insert into @t select 9
select * from @t
; with cte as (
select *
, row_number() over (partition by [Key] order by [Key]) as Picker
from @t
)
delete cte
where Picker > 1
select * from @t
quand je l'exécute sur mon système:
;WITH Customer AS
(
SELECT *, ROW_NUMBER() OVER (PARTITION BY AccountCode ORDER BY AccountCode ) AS [Version]
FROM Stage.Customer
)
DELETE
FROM Customer
WHERE [Version] <> 1
J'ai trouvé que <> 1 est meilleur que> 1.
Je pourrais créer cet index, actuellement pas présent:
USE [BodenDWH]
GO
CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
ON [Stage].[Customer] ([AccountCode])
INCLUDE ([ID])
GO
Y a-t-il une autre façon de faire cela?
À cette occasion, ce tableau n'est pas grand - environ 500 000 enregistrements sur le système en direct.
le Supprimer fait partie d'un package SSIS, il fonctionne quotidiennement et supprime environ 10-15 enregistrements par jour.
il y a des problèmes dans la manière dont les données sont structurées, j'ai juste besoin d'un code de compte pour chaque client, mais il pourrait y avoir des doublons et s'ils ne sont pas supprimés, ils brisent le colis sur une étape ultérieure.
Ce n'était pas moi qui a développé le paquet et ma portée n'est pas de ré-concevoir quoi que ce soit.
Je suis juste après la meilleure façon de vous débarrasser des duplicats, de la manière la plus rapide possible, sans avoir à vous référer à la création d'index, ni quoi que ce soit, juste le code T-SQL.
Si la table est petite et que le nombre de lignes que vous supprimez est faible, puis utilisez
;WITH Customer AS
(
SELECT *, ROW_NUMBER() OVER (PARTITION BY AccountCode ORDER BY (select null) ) AS [Version]
FROM dbo.Customer
)
DELETE
FROM Customer
WHERE [Version] > 1;
Remarque: Dans la requête ci-dessus, vous utilisez une commande arbitraire dans la clause de commande de la fenêtre ORDER BY (select null)
(appris de Livre de requête T-SQL de Itzik Ben-Gan et @aaronbertrand cité qui ci-dessus aussi) .
Si la table est grande (E.G. 5M enregistrements), supprimez IN petit nombre de lignes ou de morceaux aidera ne pas bloquer le journal des transactions et empêchera Serrure d'escalade .
Une escalade de verrouillage se produira si et uniquement si une instruction Transact-SQL a acquis au moins 5000 verrouillages sur une seule référence d'une table.
while 1=1
begin
WITH Customer AS
(
SELECT *, ROW_NUMBER() OVER (PARTITION BY AccountCode ORDER BY (select null) ) AS [Version]
FROM dbo.Customer
)
DELETE top(4000) -- choose a lower batch size than 5000 to prevent lock escalation
FROM Customer
WHERE [Version] > 1
if @@ROWCOUNT < 4000
BREAK ;
end