2010-02-11 3 views
3

Existe-t-il un moyen d'accélérer les insertions vers un mdb?Accélérer l'insertion mdb

using (StreamReader sr = new StreamReader(_localDir + "\\" + _filename)) 
    while ((line = sr.ReadLine()) != null) 
{ 
    //sanitize the data 
} 

Cela prend environ 20sec pour ~ 2mil enregistrements d'une csv mais quand j'ajoute dans l'insert mdb Je peux à peine obtenir 10.000 enregistrements 10min, afin que vous puissiez voir que ça va prendre une éternité

using (StreamReader sr = new StreamReader(_localDir + "\\" + _filename)) 
while ((line = sr.ReadLine()) != null) 
{ 
//sanitize the data 
using (OleDbConnection con = new OleDbConnection(_conStr)) 
using (OleDbCommand cmd = new OleDbCommand()) 
cmd.Parameters.AddWithValue...//I have 22 params 
cmd.ExecuteNonQuery(); 

} 

Y a-t-il un meilleur moyen? Le pool de connexion? enfiler? Voici mes constr provider = Microsoft.Jet.OLEDB.4.0; Data Source = monchemin, Jet OLEDB: Moteur type = 5"

Cordialement

_Eric

+0

Vous devez modifier votre logique d'insérer une ligne à la fois pour insérer le lot entier en une fois. Je ne sais pas C# donc je ne peux pas vous dire comment faire cela, mais cela me semble être la raison évidente pour laquelle il y a une différence entre votre code et l'importation CSV. Je dirais que votre meilleure approche est celle donnée par @Remou. –

Répondre

4

Est-il possible pour vous d'utiliser une requête qui s'insère directement à partir de csv? Par exemple:

SELECT ID,Field1 INTO NewTable 
FROM [Text;HDR=YES;FMT=Delimited;IMEX=2;DATABASE=C:\Docs\].Some.CSV 

Vous pouvez utiliser quelque chose de similaire avec délimiteurs non standard, mais vous aurez besoin d'un fichier Schema.ini dans le même répertoire que le fichier à importer. Il ne doit contenir:

[tempImportfile.csv] 
TextDelimiter=' 

Vous devrez modifier la chaîne de connexion légèrement, cela semble fonctionner:

Text;HDR=YES;FMT=Delimited;DATABASE=C:\Docs\ 
+0

Je vais donner un coup de feu, mais connaissez-vous la chaîne de connexion réelle pour définir le délimiteur à la virgule et guillemet simple pour le qualificateur de texte. http://www.connectionstrings.com/textfile n'est pas à effacer Merci – Eric

+0

FMT = Délimité devrait le faire. – Fionnuala

+1

Ci-dessus est une requête qui devrait fonctionner à partir de la connexion d'accès. – Fionnuala

3

vous auriez probablement réaliser des performances Créer une connexion/commande et l'exécuter N fois au lieu de créer N connexions/commandes

+0

Je donne un coup de feu et maintenant afficher les résultats, grâce à l'aide – Eric

+0

(StreamReader sr = new StreamReader (_localDir + "\\" + _filename)) utilisant (OleDbConnection con = new OleDbConnection (_conStr)) en utilisant (OleDbCommand cmd = new OleDbCommand()) while ((line = sr.ReadLine())!= Null) n'a pas aidé vraiment, il a fait 275 enregistrements en 1 min, mais grâce – Eric

1

Un autre changement qui pourrait accélérer un peu plus est de préparer une fois la commande. et créer tous les paramètres.Puis dans la boucle, il suffit d'affecter le para mesurer les valeurs et les exécuter à chaque fois. Cela peut éviter l'analyse et la vérification sémantique de l'instruction à chaque itération et devrait améliorer le temps. Cependant, je ne pense pas que ce serait une amélioration significative. L'analyse syntaxique doit être une partie relativement faible du coût total, même si elle est analysée à chaque fois.

+0

Merci, je pense que c'est ce que je suis en train d'essayer ce après l'utilisation de (OleDbCommand cmd = new OleDbCommand()) Je mets la cmd à la con et l'ouvrir également mettre le texte cmd.command à INSERT INTO MyTable VALUES (@ p1, @ p2 ... puis b4 j'exécute la commande dans le temps ((line = sr.ReadLine()) i faire un cmd.params.clear et démissionner pour la ligne courante.Je peux même boucler avec tout sauf l'executenonquery et son joli peppy.Sans ExecuteNonquery je peux boucler les enregistrements 2m + en 32514 ms, quand j'ajoute le executeNonQuery je reçois ~ 80000 par minute – Eric

+0

@Eric: Le fichier .mdb se trouve-t-il sur un lecteur local ou sur un lecteur réseau? –

+0

Il s'agit d'un fichier local. n read-> sanitize-> écrivez le csv dans ~ 40sec puis appelez Process.Start ("msaccess.exe", myNewFile) et tout fait en moins d'une minute – Eric

3

Microsoft Jet pour gérer Sql l'analyse syntaxique (INSERT/UPDATE) est lente en général. En d'autres termes, vous pouvez avoir le code le plus efficace possible, mais le point d'étranglement est Jet. Gardez à l'esprit, que dans votre envoi d'origine votre connexion (ouvrir un fichier, créer un verrou, rechercher un fichier, insérer une ligne, disposer le verrou, fermer le fichier, disposer de l'objet) pour chaque ligne. Vous devez vous connecter ONCE (en dehors du temps), lire les lignes, générer Sql (OleDbCommand), puis exécuter.

+2

Ce n'est tout simplement pas vrai. Jet est généralement très rapide pour ce genre de chose si vous lui dites de faire la bonne chose. Le code de la question d'origine le fait une ligne à la fois, autant que je sache, et cela va être beaucoup plus lent que de faire l'insertion dans un lot (qui est le point de comparaison). Tout moteur de base de données va ralentir l'exécution de 2 millions d'insertions à une rangée plutôt que d'insérer 2 millions de lignes dans un lot. –

+0

J'aimerais voir vos repères comparés aux miens. J'ai trouvé que passer par Interop est plus rapide quand on parle à Excel ou à Access, en ignorant complètement Jet. Si je peux voir comment Jet est plus efficace, alors je vais manger mon down-vote facilement. En ce qui concerne le traitement par lots ou l'absence de traitement par lots, ce n'était pas le cas. S'il vous plaît noter ma commande supplémentaire sur son approche de l'ouverture/fermeture (rincer, répéter) pour le même fichier mdb pour chaque ligne et comment cela n'est pas efficace du tout. – Michael

+0

Si vous parlez de données Access/Jet, vous ne pouvez pas contourner Jet!On peut utiliser des méthodes inefficaces pour parler à Jet et obtenir de mauvaises performances, ce qui était le cas dans la question initiale (c'est-à-dire une succession d'insertions à une rangée, au lieu d'une insertion par lots). –