J'ai un insert qui utilise une vérification de condition pour un NOT IN. Il y a environ 230k lignes dans la sous-requête NOT IN.Aidez à optimiser cette requête avec une énorme instruction IN
INSERT INTO Validate.ItemError (ItemId, ErrorId, DateCreated)
(
SELECT ItemId, 10, GetUTCDate()
FROM Validate.Item
INNER JOIN Refresh.Company
ON Validate.Item.IMCompanyId = Refresh.Company.IMCompanyId
WHERE Refresh.Company.CompanyId = 14
AND
(
IMAccountId IS NULL OR NOT IMAccountId IN
(
SELECT RA.IMAccountId
FROM Refresh.Account RA
INNER JOIN Refresh.BalancePool BP
ON RA.BalancePoolId = BP.BalancePoolId
WHERE BP.CompanyId = 14
)
)
)
Lorsque je l'exécute tel quel, cela prend environ 30 minutes (yacks!). Le nombre de valeurs dans la table Validate.Item peut être de 150 lignes à plus de 200 Ko, ce qui vous permet de voir à quel point cela peut être douloureux.
Il existe des index sur tous les champs pertinents des tableaux, et aucun n'est trop fragmenté.
Ma première pensée était de faire en morceaux et le jeter dans une boucle while:
DECLARE @StartId int, @EndId int, @MaxId int
SELECT @MaxId = MAX(AccountId) FROM Refresh.Account
SET @StartId = 1
SET @EndId = 1000
WHILE (@StartId < @MaxId)
BEGIN
INSERT INTO Validate.ItemError (ItemId, ErrorId, DateCreated)
(
SELECT ItemId, 10, GetUTCDate()
FROM Validate.Item
INNER JOIN Refresh.Company
ON Validate.Item.IMCompanyId = Refresh.Company.IMCompanyId
WHERE Refresh.Company.CompanyId = 14
AND
(
IMAccountId IS NULL
OR NOT IMAccountId IN
(
SELECT RA.IMAccountId
FROM Refresh.Account RA
INNER JOIN Refresh.BalancePool BP
ON RA.BalancePoolId = BP.BalancePoolId
WHERE BP.CompanyId = 14
AND RA.AccountId BETWEEN @StartId AND @EndId
)
)
)
SET @StartId = @StartId + 1000
SET @EndId = @EndId + 1000
END
En procédant ainsi, me filets un temps d'environ une minute par boucle; multipliez cela par 230 fois et nous avons un nombre encore plus ridicule.
Dites-moi si vous avez une meilleure idée de comment optimiser cela. Sans cette requête, le processus entier ne prend que 8 secondes; c'est juste la taille de la table Refresh.Account qui jette tout dans le chaos.
TIA!
Valkyrie
Vous pourriez avoir mal optimisé/tables indexées que vous pourriez vouloir attaquer en premier. –
@Kragen: Comment avez-vous indenté le code? un outil? – shahkalpesh
Pourriez-vous s'il vous plaît poster le plan de requête tel qu'il est maintenant? – Quassnoi