11
votes

Le moyen le plus rapide d'insérer un très grand nombre d'enregistrements dans une table en SQL

Le problème est que nous avons un grand nombre d'enregistrements (plus d'un million) à insérer dans une seule table d'une application Java. Les enregistrements sont créés par le code Java, ce n'est pas un déplacement d'une autre table, donc insérer / sélectionner ne vous aidera pas.

Actuellement, mon goulot d'étranglement est les relevés d'insertion. J'utilise PrepareStatement pour accélérer le processus, mais je ne peux pas obtenir plus de 50 recods par seconde sur un serveur normal. La table n'est pas du tout compliquée et il n'y a pas d'index défini dessus.

Le processus prend trop de temps et le temps qu'il faut faire des problèmes.

Que puis-je faire pour obtenir la vitesse maximale (insertion par seconde) possible?

Base de données: MS SQL 2008. Application: Java basé sur Java, à l'aide du pilote Microsoft JDBC.


0 commentaires

7 Réponses :


2
votes

Avez-vous examiné les opérations en vrac Opérations en vrac ?


1 commentaires

Je vais essayer, je suppose que ce sera ma meilleure solution. Le seul problème est que je dois créer des fichiers, puis exécuter l'opération et que je devrai coder pour les différents scénarios pouvant arriver pour les conditions de stockage et de réseau de fichiers.



10
votes

lot les inserts. C'est-à-dire seulement envoyer 1000 lignes à la fois, plutôt une ligne à la fois, vous réduisez donc énormément les appels ronds / serveurs

Effectuer des opérations de lot sur MSDN pour le pilote JDBC. C'est la méthode la plus simple sans réingénierie pour utiliser des méthodes de vrac authentiques.

Chaque insert doit être analysé et compilé et exécuté. Un lot signifiera beaucoup moins d'analyse / compilation car un inserts de 1000 (par exemple) sera compilé en une fois sur

Il y a de meilleures façons, mais cela fonctionne si vous êtes limité à des inserts générés


5 commentaires

Je pense que le voyage aller-retour est une très petite partie du retard, car avec 50 transactions par seconde, il faut 20 ms pour chaque requête à exécuter. Le retour aller-retour est inférieur à 1 ms. J'ai fait d'autres optimisations pour supprimer des voyages ronds, mais ils n'ont pas beaucoup aidé. À moins que le loting des insertions entraînera une grande partie des transformations internes SQL plus efficaces. Est-ce que ça?


@Irchi: Chaque insert doit être analysé et compilé et exécuté. Un lot signifiera beaucoup moins d'analyse / compilation car un inserts de 1000 (par exemple) sera compilé en une seule fois.


@Irchi: J'essaierais cela avant de ré-ingénieur le code à nous une approche BCP


L'une des raisons pour lesquelles cela est plus efficace est que l'analyseur de requête MySQL n'a pas à analyser chaque requête. J'ai changé un morceau de mon code en Java (parler à MySQL en cluster) pour utiliser des inserts par lots de 1000 et la vitesse augmentée de 100x (10000%)


J'ai testé cela et remarqua que les performances vont de 25 heures / seconde à 107 lignes / seconde si je définis Conn.setAutocommit (Faux); Cela semble un cadre essentiel, non mentionné dans le lien MSDN ...



0
votes

regarder dans Utilitaire BCP de SQL Server.

Cela signifierait un gros changement dans votre approche en ce que vous généreriez un fichier délimité et en utilisant un utilitaire externe pour importer les données. Mais il s'agit de la méthode la plus rapide d'insertion d'un grand nombre d'enregistrements dans un DB SQL Server et accélérera votre temps de charge par de nombreuses ordres de grandeur.

En outre, est-ce une opération ponctuelle que vous devez effectuer ou quelque chose qui se produira régulièrement? Si c'est une fois, je suggérerais de ne même pas coder ce processus mais n'effectuez pas d'exportation / importation avec une combinaison d'utilitaires de DB.


0 commentaires

1
votes

Avez-vous envisagé d'utiliser Mises à jour par lots ?


1 commentaires

Merci, je suppose que cela peut être utile aussi. Mais je vais d'abord essayer un insert en vrac, il semble plus prometteur!



6
votes

Utilisez insert en vrac - il est conçu pour exactement ce que vous êtes demandant et significativement augmente la vitesse des inserts.

En outre, (juste au cas où vous n'avez vraiment pas d'index), vous pouvez également envisager Ajout d'index d'index - certains index (la plupart d'un index sur la clé primaire) peuvent améliorer les performances de insertions.

Le taux réel à laquelle vous devriez pouvoir insérer des enregistrements dépendra des données exactes, la structure de la table et également sur le matériel / la configuration du serveur SQL lui-même, donc je ne peux donc pas vraiment vous donner des chiffres. < / p>


1 commentaires

En fait, j'ai un indice sur le PK qui est groupé et que les données sont insérées dans la commande PK, donc je ne pense pas que cela n'aura aucun effet. Je vais essayer un insert en vrac, je suppose que c'est ma solution.



0
votes

Je recommanderais d'utiliser un moteur ETL pour cela. Vous pouvez utiliser Pentaho . C'est gratuit. Les moteurs ETL sont optimisés pour effectuer une charge en vrac sur les données et également toutes les formes de transformation / validation requises.


0 commentaires

1
votes

Y a-t-il une contrainte d'intégrité ou une gâchette sur la table? Si tel est le cas, le laisser tomber avant que des inserts aidera, mais vous devez être sûr de vous permettre de vous permettre des conséquences.


1 commentaires

Il y a deux contraintes FK, je prévoyais de les supprimer et de le faire essayer. Mais l'insert en vrac a la possibilité d'ignorer les contraintes, donc je suppose que l'utilisation d'insert en vrac, j'aurai tous les avantages dont j'ai besoin.