Améliorer l'INSÉRER DANS - DE SÉLECTIONNER, de Requête SQL
Actuellement j'ai eu ce type de requête générée par programmation (c#)
INSERT INTO TableName (Field1, Field2, Field3)
SELECT Field1, Field2, Field3 FROM TableName2
Le problème est que le SELECT peut avoir un résultat de nombreux enregistrements (un million), c'est donc prendre beaucoup de temps et le résultat est un délai d'attente de connexion.
Aussi, si j'ai séparé tous les insèrent dans les unique d'insertion (pour cet exemple, un million de requêtes de type insert), c'est prendre le temps très long à exécuter ... mais ça marche ...
Est-il un moyen pour que je puisse améliorer ce type de requête ?
- Je utiliser MSSQl 2005
Thx
Vous devez vous connecter pour publier un commentaire.
J'ai trouvé que, si vous avez beaucoup d'INSÉRER des instructions qui sont exécutées dans l'ordre, vous pouvez améliorer les performances par l'ajout d'un "ALLER" déclaration après chaque xxxx nombre d'instructions insert:
Une autre possibilité peut-être, est de s'assurer que votre INSERT INTO .. SELECT DE la requête n'a pas d'insérer le tout en une seule fois, au lieu d'utiliser une sorte de technique d'échange:
Bien, si c'est une copie, je me demande si on ne doit pas regarder en charge des outils?
Si vous avait un
Where
clause, je voudrais vérifier qu'il est correctement indexé...En outre:
pensez à supprimer l'ensemble de la table et à l'aide de SELECT SUR ?(voir les commentaires)Ok, il y a quelques questions fondamentales.
I\O - l'Insertion dans une table lors de la lecture à partir d'une autre table plus susceptibles de causer la contention de disque si les tables ne sont pas sur des disques séparés. Mettre l'adversaire de tableaux sur physiquement les différentes broches.
De Journal de Transaction, vous devez Vous assurer que votre journal des transactions est sur son propre disque, ou de travailler dans des transactions plus petites (quelques milliers de lignes à la fois) ou de l'utilisation de la PCA\Bulk Insert qui n'est pas connecté.
Index cluster - Si vous insérez l'ensemble de ces lignes dans une table cible, et c'est l'index cluster(l'ordre physique des données sont écrites sur le disque) n'est pas écrit de manière séquentielle, les e /s disque exigences de passer par le toit à cause de la page se divise et une ré-allocation. Une solution facile peut-être de créer un index cluster sur la table de destinataires qui est une séquence de graines de clé. Cela permettra d'assurer que vous obtenez les écritures séquentielles dans la table, et presque toujours à la fin.
Fichier d'Extension Assurer que vous avez SQL définie à l'augmenter de fichiers à un taux décent, de l'ordre de 10% ou plus. Sinon, il faudra constamment redimensionner les fichiers et zéro sur le disque. Il existe des moyens pour éviter d'avoir à remettre à zéro le disque en tant que bien, comme permettant à l'essentiel Opération de Fichier autorisation dans vos stratégies de groupe pour le Service Sql utilisateur.
Franchement, d'autres que cela et quelques autres suggestions, il est très peu probable que vous faire un insert avec des millions de lignes dans une transaction n'est vraiment rapide. Si vous avez ce par le biais d'Insertion en bloc, il serait considérablement plus rapides, mais il pourrait ne pas être ce dont vous avez besoin à partir d'un point de vue application.
Ensemble
CommandTimeout
propriété de laSqlCommand
vous êtes à l'aide d'un bon de valeur (10 minutes environ). Rappelez-vous queCommandTimeout
est en secondes.Quelques bonnes réponses ici.
Voudrais juste ajouter que si vous avez des indices sur la table de destination ils vont ralentir le fonctionnement. Cependant, la reconstruction de l'index peut parfois prendre beaucoup de temps si vous ne la chute de créer la technique.
Si vous ne voulez pas laisser tomber l'index, utilisez un
ORDER BY
dans votreSELECT
qui correspond à la destination index cluster, ce qui semble aider (probablement contribue à réduire les fractionnements de page).Vous n'indique pas quel est le problème de vos problèmes avec cette approche. Évidemment, OÙ serait restreindre le jeu d'enregistrements. Mais si le résultat ne va pas être modifiés dans la Nouvelle Table, alors pourquoi répliquer les données? Pourquoi ne pas interroger directement de la Source?
en vrac charge par l'aide d'un fichier et puis bcp/INSERTION en bloc ou par lots en lots de 5 km ou si
En premier lieu, n'essayez jamais d'insérer un million d'enregistrements par le biais de C#. Jamais de grands groupes d'enregistrements un à un. C'est un travail qui doit être fait à la base de données par la base de données. Utilisez l'instruction bulk insert ou SSIS ou DTS pour ce faire. Et puis le programmer comme un travail pendant les heures creuses. Si elle prend trop de temps, alors je suggère que vous l'exécutez par lots de plusieurs milliers (vous aurez à jouer avec votre propre base de données pour voir quel est le meilleur choix est que le nombre que vous pouvez en toute sécurité dépend beaucoup sur les tables, l'indexation de la rapidité de votre serveur est et combien d'utilisateurs sont aussi essayer de faire travailler contre les mêmes tables.
Un autre moyen que nous avons utilisé dans le passé est de créer une table temporaire avec les clés primaires, nous voulons déplacer et utiliser la boucle while. De cette façon, vous pouvez le faire dans une sorte de bloc de la mode afin de vous éviter de la grande opération de surcharge si vous avez annulé et qu'il a du faire reculer.
Fondamentalement, ce que vous finissez par faire un insert into nom_table (...) sélectionner (...) du nom de la table où la clé primaire dans (sélectionnez haut 10000 clé de temptable)
le top 10000 vous voulez dans une deuxième ensemble de résultats de sorte que vous pouvez les supprimer de la table temporaire afin de ne pas se faire traiter de nouveau.
Encore un autre moyen serait d'utiliser les curseurs pour réduire le nombre d'enregistrements processus à la fois.
Une autre méthode de boucle serait de faire quelque chose comme ceci dans une boucle while.
declare @stop comme int
set @stop = (select count(primaryKey) from tableName où primaryKey pas dans destinstiontable)
while (@stop > 0)
begin transaction
insérer dans destinationTable (...)
sélectionnez (...) à partir de sourcetable où primaryKey pas dans (sélectionnez primarykey de destinationtable)
commettre
set @stop = (select count(primaryKey) from tableName où primaryKey pas dans destinstiontable)
fin
Pas le plus efficace mais il devrait fonctionner et devrait vous permettre de tenir le journal des transactions vers le bas. Sauf si vous en avez besoin, assurez-vous également d'utiliser le pas de verrouillage de mot-clé afin de ne pas bloquer les autres opérations lors de ce grand déplacement (sauf si vous utilisez BCP ou DTS, car ils sont beaucoup beaucoup plus rapide).
Certains de ce qui a été dit, c'est probablement votre meilleur pari si. L'utilisation de la PCA, DTS, ou certains autres en vrac de l'outil. Si vous pouvez supprimer les index, il va rendre les choses vont beaucoup plus vite.
Avez-vous testé le sql à l'aide de sql server management studio pour voir combien de temps cela prend? Je commencerais par là.
Vous pouvez améliorer les performances de la sélectionner.
Et vous pourriez être en mesure d'améliorer la performance de l'indicateur tablock, des conseils sur la table de votre insertion dans la.