Question

Je dois insérer 800000 enregistrements dans une table MS Access. J'utilise Delphi 2007 et les composants TAdoXxxx. Le tableau contient des champs entiers, un champ de flotteur et un champ de texte avec un seul caractère. Il y a une clé primaire sur l'un des champs entiers (qui ne sont pas AutoInc) et deux index sur un autre entier et le champ de flotteur.

Insertion des données à l'aide AdoTable.AppendRecord(...) prend> 10 minutes qui n'est pas acceptable puisque cela se fait à chaque fois que l'utilisateur commence à utiliser une nouvelle base de données avec le programme. Je ne peux pas préremplir la table parce que les données proviennent d'une autre base de données (non accessible par ADO).

J'ai réussi à descendre à environ 1 minute en écrivant les enregistrements dans un fichier texte séparé par onglet et en utilisant un objet tAdoCommand pour exécuter

insert into table (...) select * from [filename.txt] in "c:\somedir" "Text;HDR=Yes"

Mais je n'aime pas les frais généraux de cela.

Il doit y avoir une meilleure façon, je pense.

EDIT:

Quelques informations supplémentaires:

  • MS Access a été choisi parce qu'il n'a pas besoin d'installation supplémentaire sur la machine cible (s) et la base de données tout est contenu dans un fichier qui peut être facilement copié.
  • Ceci est une application unique de l'utilisateur.
  • Les données seront insérées une seule fois et ne changera pas pour la durée de vie de la base de données. Bien que, la table contient une zone supplémentaire qui est utilisée comme un indicateur pour indiquer que l'enregistrement correspondant dans une autre base a été transformé par l'utilisateur.
  • Une minute est acceptable (jusqu'à 3 minutes serait trop) et travaille ma solution, mais il me semble trop compliqué, donc je pensais qu'il devrait y avoir un moyen plus facile de le faire.
  • Une fois que les données ont été insérées, la performance de la table est tout à fait bonne.
  • Quand j'ai commencé la planification / mise en œuvre de la fonction du programme de travail avec la base de données d'accès à la table n'a pas été nécessaire. Il ne fallut plus tard, quand une autre caractéristique a été demandée par le client. (Est-ce pas toujours le cas?)

EDIT:

De toutes les réponses que je suis tellement loin, il semble que je l'ai déjà obtenu la méthode la plus rapide pour insérer des données que beaucoup dans une table d'accès. Merci à tout le monde, je vous remercie de votre aide.

Était-ce utile?

La solution

semble la solution la plus rapide en fonction de votre texte, mais vous pouvez l'obtenir plus rapidement si vous pouvez obtenir un MS Access préalloués dans une taille à la fin un. Vous pouvez le faire en remplissant une base de données utilisateur typique, la fermeture de l'application (donc les tampons sont vidées) et de faire une suppression manuelle de tous les enregistrements de cette grande table -. Mais pas le rétrécissement / compactant

Alors, utilisez ce fichier pour démarrer le réel remplissage - L'accès ne réclamera aucun (ou très peu) d'espace disque supplémentaire. Ne pas remeber si MS Access ont un moyen d'automatiser cela, mais il peut aider beaucoup ...

Autres conseils

Puisque vous avez dit que les données 800K enregistre ne changera pas pour la vie de la base de données, je vous suggère un lien vers le fichier texte comme une table, et sauter l'insert tout à fait.

Si vous insistez sur le tirant dans la base de données, puis 800.000 enregistrements en 1 minute est plus de 13.000 / seconde. Je ne pense pas que vous allez battre dans MS Access.

Si vous voulez qu'il soit plus réactif pour l'utilisateur, alors vous pouvez envisager de charger une série de données minimales, et la mise en place d'un fil d'arrière-plan pour charger le reste pendant qu'ils travaillent.

Il serait plus rapide sans les indices. Pouvez-vous les ajouter après l'importation?

Il y a un certain nombre de suggestions qui peuvent intéresser dans ce fil lente écriture disque MSAccess

Qu'en est-il sauter le fichier texte et en utilisant ODBC ou OLEDB importer directement à partir de la table source? Cela signifierait modifier votre clause FROM d'utiliser le nom de la table source et une chaîne de connexion appropriée comme IN « » une partie de la clause FROM.

EDIT: En fait, je vous dis le format d'origine est de voir xBase, il devrait donc être possible d'utiliser le ISAM xBase qui fait partie de Jet au lieu d'avoir besoin ODBC ou OLEDB. Cela ressemblerait à quelque chose comme ceci:

INSERT INTO table (...) 
SELECT * 
FROM tablename IN 'c:\somedir\'[dBase 5.0;HDR=NO;IMEX=2;];

Vous pourriez avoir à bidouiller que -. Je viens attrapé la chaîne de connexion pour une table liée pointant un fichier DBF, de sorte que les paramètres peuvent être légèrement différents

Que diriez-vous d'un autre arrangement ...

Serait-il une possibilité de faire une copie d'un fichier de base de données Access existante qui a ce tableau dont vous avez besoin et puis supprimez simplement toutes les autres données là-dedans outre une grande table (ne sais pas si l'accès a un équivalent à quelque chose comme "truncate table" dans le serveur SQL)?

Je remplacerais MS Access avec une autre base de données, et votre situation je vois SQLite est le meilleur choix, il ne nécessite aucune installation dans la machine client, et sa base de données très rapide et une de la meilleure solution de base de données intégrée.

Vous pouvez l'utiliser en Delphi de deux façons:

  1. Vous pouvez télécharger le moteur de base de données dll sur le site SQLite et utiliser le composant de Delphi gratuit pour y accéder comme Delphi composants SQLite ou SQLite4Delphi

  2. Utilisez DISQLite3 qui ont le moteur construit, et vous ne devez pas distribuer le dll avec votre application, ils ont une version gratuite; -)

si vous avez encore besoin d'utiliser MS Access, essayez d'utiliser TADOCommand avec SQL Insert statment directement au lieu d'utiliser TADOTable, qui devrait être plus rapide que d'utiliser TADOTable.Append;

Vous ne serez pas importer 800.000 enregistrements en moins d'une minute, comme quelqu'un l'a dit; c'est vraiment rapide déjà.

Vous pouvez ignorer l'ennuyeux traduire à fichier texte étape si vous utilisez la bonne méthode (DAO de recordsets) pour faire les inserts. Voir une question précédente, j'ai demandé et avait répondu sur StackOverflow: MS Access: Pourquoi est-ADODB.Recordset.BatchUpdate beaucoup plus lent que Application.ImportXML

?

Ne pas utiliser INSERT INTO même avec DAO; c'est lent. Ne pas utiliser ADO soit; c'est lent. Mais OAC + Delphi + + Recordsets instanciation de l'objet COM DBENGINE directement (au lieu de via l'objet Access.Application) vous donnera beaucoup de vitesse.

Vous êtes à la recherche dans la bonne direction dans un sens. En utilisant une seule déclaration à insérer en vrac sera plus rapide que d'essayer de parcourir les données et l'insérer ligne par ligne. L'accès, étant une base de données basée sur des fichiers sera très lent dans les écritures itératives.

Le problème est que l'accès est la manipulation de la façon dont il optimise les écritures en interne et il n'y a pas vraiment moyen de le contrôler. Vous avez probablement atteint l'efficacité maximale d'une instruction INSERT. Pour une vitesse supplémentaire, vous devriez probablement évaluer s'il y a une façon d'écrire autour de 800.000 enregistrements à la base de données chaque fois que vous lancez l'application.

SQL Server Express (gratuit) et de s'y connecter à partir d'Access une table externe. SQL Express est beaucoup plus rapide que MS Access.

Je préremplir la base de données, et de les remettre le fichier lui-même, plutôt que de remplir une base de données existante (mais vide).

Si les données que vous devez remplir les modifications, puis garder une base de données d'accès ODBC (fichier MDB) synchronisé sur le serveur en utilisant un peu de code pour voir des changements dans la base de données principale et les copier dans la base de données d'accès.

Lorsque l'utilisateur demande une nouvelle base de données zip le MDB, le transférer à eux, et ouvrez-le.

Sinon, vous pourrez peut-être trouver le code qui ouvre et insère des données dans les bases de données directement.

Sinon, tour à tour, vous pourrez peut-être trouver un autre format (autre que csv) dont l'accès peut importer qui est plus rapide.

-Adam

Vérifiez également combien de temps il faut pour copier le fichier. Ce sera la limite inférieure de la vitesse, vous pouvez écrire des données. Dans la DB comme SQL, il faut généralement un utilitaire de chargement en vrac pour se rapprocher de cette vitesse. Pour autant que je sache, MS n'a jamais créé un outil pour écrire directement aux tables MS Access bcp de chemin fait. Des outils spécialisés ETL permettra également d'optimiser quelques-unes des étapes entourant l'insert, comme la façon dont SSIS fait des transformations en mémoire, DTS a également quelques optimisations.

Peut-être que vous pourriez ouvrir un jeu d'enregistrements ADO à la table avec le mode de verrouillage adLockBatchOptimistic et CursorLocation adUseClient, écrivez toutes les données à la recordset, puis faire une mise à jour batch (rs.UpdateBatch).

Si elle vient de dBase, vous pouvez copier uniquement les données et les fichiers d'index et joindre directement sans chargement? Devrait être assez efficace (des personnes qui vous apportent FoxPro.) J'imagine qu'il utiliserait aussi les indices existants.

Au moins, il devrait y avoir une seule commande assez efficace d'importation.

Combien les 800.000 dossiers changent d'une création à l'autre? Serait-il possible d'effectuer une pré remplir les enregistrements, puis simplement mettre à jour ceux qui ont changé dans la base de données externe lors de la création de la nouvelle base de données?

Cela peut vous permettre de créer rapidement le nouveau fichier de base de données.

Quelle est la vitesse de votre disque tournant? Si c'est 7200RPM, puis 800.000 lignes en 3 minutes est encore 37 lignes par révolution de disque. Je ne pense pas que vous allez faire beaucoup mieux que cela.

En attendant, si l'objectif est de rationaliser le processus, que diriez-vous un lien de table?

Vous dites que vous ne pouvez pas accéder à la base de données source via ADO. Pouvez-vous mettre en place un lien de table dans MS Access à une table ou une vue dans la base de données source? Ensuite, une simple requête append à partir du lien de table copiait les données au-dessus de la base de données source vers la base de données cible pour vous. Je ne suis pas sûr, mais je pense que ce serait assez rapide.

Si vous ne pouvez pas mettre en place un lien de table jusqu'à ce que l'exécution, vous pourriez peut-être construire le lien de table via ADO programatically, puis construire la requête append programatically, puis appeler la requête append.

HI La meilleure façon est insertion en bloc à partir du fichier de texte comme ils ont dit vous devez insérer vos enregistrements dans le fichier txt en vrac puis insérez le fichier txt dans la table ce temps doit être inférieur à 3 secondes.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top