2010-04-30 5 views
3

Avoir un problème majeur tirer les cheveux avec des inserts extrêmement lents de Delphi 2010 à un serveur distant 5,09 MySQL. Jusqu'à présentinsert extrêmement lent de Delphi à base de données MySQL à distance

, j'ai essayé:

  • ADO à l'aide de MySQL pilote ODBC
  • Zeoslib v7 Alpha
  • MyDAC

Je l'ai utilisé batching et insertion directe avec ADO (en utilisant le tableau access), et avec Zeos, j'ai utilisé l'insertion SQL avec une requête, puis utilisé le mode Table direct et également mis en cache le mode Table en utilisant applyupdates et commit. Avec MyDAC je mode d'accès de table, puis insérez SQL directe et insert SQL dosé

Toutes les technologies que j'ai essayé, je mis en compression et en dehors sans différence discernable.

Jusqu'à présent, j'ai vu à peu près la même chose à travers le tableau 7.5 enregistrements par seconde !!! Maintenant, je suppose que le serveur distant est lent, mais MySQL Workbench est incroyablement rapide, et la boîte à outils Migration a géré la migration initiale très rapidement (pour être honnête, je ne me souviens pas à quelle vitesse - ce qui signifie type de ce qu'il était rapide)

Modifier 1

il me est plus rapide pour d'écrire le SQL dans un fichier, télécharger le fichier sur le serveur via FTP, puis l'importer directe sur la serveur distant - Je me demande s'ils limitent peut-être le trafic MySQL entrant, mais cela n'explique pas pourquoi le MySQL Workbench était si rapide!

Edit 2

, le code a été au niveau le plus élémentaire:

while not qMSSQL.EOF do 
begin 
    qMySQL.SQL.Clear; 
    qMySQL.SQL.Add('INSERT INTO tablename (fieldname1) VALUES (:fieldname1)'); 
    qMySQL.ParamByName('fieldname1').asString:=qMSSQL.FieldByName('fieldname1').asString; 
    qMySQL.ExecSQL; 
    qMSSQL.Next; 
end; 

J'ai ensuite essayé

qMySQL.CachedUpdates:=true; 
i:=0; 
while not qMSSQL.EOF do 
begin 
    qMySQL.SQL.Clear; 
    qMySQL.SQL.Add('INSERT INTO tablename (fieldname1) VALUES (:fieldname1)'); 
    qMySQL.ParamByName('fieldname1').asString:=qMSSQL.FieldByName('fieldname1').asString; 
    qMySQL.ExecSQL; 
    inc(i); 
    if i>100 then 
    begin 
    qMySQL.ApplyUpdates; 
    i:=0; 
    end; 
    qMSSQL.Next; 
end; 
qMySQL.ApplyUpdates; 

Maintenant, dans ce code avec CachedUpdates:=False (qui, évidemment, jamais vraiment écrit à la base de données) la vitesse était vif et rapide !! Pour être tout à fait honnête, je pense que c'est la connexion - je sentir c'est la connexion ... J'attends juste qu'ils reviennent à moi!

Merci pour votre aide!

+0

Il sera très utile de détecter votre goulot d'étranglement si vous affichez votre code –

+1

Quelle est la rapidité de l'insertion si vous utilisez un serveur local? Peut-être que c'est un problème lié au transport (connexion lente). – mjn

+0

Votre code n'est pas correct. Définissez le code SQL * en dehors de la boucle, puis appelez Prepare. Dans la boucle, il suffit d'assigner le paramètre et de l'exécuter, sinon vous perdez les avantages des paramètres. Démarrer une transaction de manière explicite en dehors de la boucle, et valider à la fin. CachedUpdates défini sur False signifie que les données vont directement dans la base de données et ne sont pas mises en cache localement. N'utilisez pas CachedUpdates, ils n'étaient pas destinés à la vitesse. –

Répondre

0

Utilisez-vous des paramètres de requête? Le moyen le plus rapide d'insérer devrait être d'utiliser des requêtes simples et des paramètres (par exemple INSERT INTO table (field) VALUES (: field)), de préparer la requête puis d'assigner des paramètres et de les exécuter autant de fois que nécessaire. (ne pas utiliser toute la saveur de autocommit)

que dans la plupart des bases de données évite à chaque fois difficile parse la requête est exécutée, ce qui exige du temps. Les paramètres permettent d'analyser la requête une seule fois, puis de la ré-exécuter plusieurs fois si nécessaire.

Utilisez le serveur facilites pour vérifier ce qui se passe - beaucoup offrent un moyen de vérifier ce que les déclarations en cours d'exécution font.

+0

J'ai utilisé des paramètres de requête et des insertions par lots au début (j'essaie toujours d'utiliser SQL d'abord si je peux) mais la vitesse moyenne était la même :( –

+0

Je n'utiliserais pas ADO batch insert, il pourrait réduire les roundtrips mais il obtient le contrôle du À mon humble avis, la méthode fastests est de laisser les instructions aller directement à la base de données avec moins de frais généraux possible.Tout d'abord, vous devez d'abord trouver où le goulot d'étranglement est vraiment –

+0

Réponse correcte à Idsandon qui a mentionné la vérification du serveur –

0

Je ne suis pas sûr de Zeoslib, mais en utilisant ADO avec pilote ODBC, vous ne serez pas le meilleur moyen d'insérer les enregistrements, ici quelques étapes qui peuvent rendre votre insertion plus rapide:

  1. utilisation MyDAC pour un accès direct, ils fonctionnent sans le lent ODBC> ADO> OLEDB> MySqlLib pour se connecter à Mysql.

  2. Ouvrir la connexion au premier avant l'insertion.

  3. si vous avez grande insertion tels que 1000 ou plus, essayez transaction d'utilisation et engager après 100 enregistrement ou plus dépendre du nombre de dossiers.

Point 3 peut rendre votre insertion plus rapide, même avec ZeosLib ou ADO.

+0

Merci pour la réponse, mais j'ai déjà essayé 2 & 3 (toujours en train d'installer MyDAC pour le moment) J'avais espéré que l'insertion par lots serait plus rapide, mais elle est sortie à la même vitesse moyenne que l'insertion d'un enregistrement à un temps sur le fil !? –

3

Vous pouvez AnyDAC et tableau fonction DML. Il peut accélérer un SQL INSERT standard pour quelques fois.

+0

Merci Dmitry, j'ai essayé une démo et la fonctionnalité Array DML semble vraiment intéressante - mais hélas la même vitesse –

+0

Nous avons essayé array dml avec MySQL - C'était vraiment rapide, il semble que quelque chose sur votre système fait des problèmes – oodesigner

0

Vous avez deux choses distinctes ici. Tout d'abord, votre programme Delphi crée des instructions Insert et les envoie au serveur de base de données, puis le serveur les gère. Vous devez examiner les deux extrémités pour trouver le goulot d'étranglement. Je ne suis pas familier avec les outils MySQL, mais je parie que vous pourriez trouver un profileur SQL pour cela assez facilement. Utilisez-le pour profiler vos inserts à partir de l'application Delphi et comparez-les aux insertions en cours d'exécution à partir de l'outil Workbench pour voir s'il existe une différence significative.

Dans le cas contraire, le ralentissement est dans votre application. Essayez de l'accrocher à Sampling Profiler ou à un autre outil de profil qui comprend Delphi, et il vous montrera où vous passez beaucoup de temps. Une fois que vous le savez, alors vous pouvez travailler sur l'attaque du problème, ou peut-être revenir ici pour poser une question plus spécifique. Mais jusqu'à ce que vous sachiez d'où vient le problème, toutes les réponses que vous obtiendrez ici seront des suppositions éclairées au mieux.

+0

Merci Mason, je suis p peu sûr que c'est la vitesse du serveur et pas mon code, je n'étais pas sûr à 100% que j'utilisais les libs mysql correctement, et/ou quelles étaient les meilleures pratiques en ce qui concerne Delphi, mais elles semblent être similaires à ce que j'ai essayé en tous cas. –

1

Désolé cette réponse vient longtemps après que vous ayez posé la question.

J'ai eu un problème similaire. BDS2006 à MySQL via ODBC à travers le réseau - a pris 25 minutes pour fonctionner - environ 25 insertions par seconde. J'utilisais une connexion TDatabase et attachait le TTable Tquery à celui-ci. Préparé les instructions SQL.

La principale amélioration est quand j'ai commencé à partir des transactions dans la boucle. Un exemple simple, Memebrships ont une période membre. Commencez une transaction avant l'insertion de l'adhésion et des membres, validez après. Le nombre d'appartenances était de 01585 et avant les transactions, il fallait 279,90 secondes pour traiter tous les enregistrements d'adhésion, mais après 6,71 secondes.

Presque trop bon à croire et travaille toujours à corriger le code pour les autres bits lents.

Peut-être que Mark vous avez résolu votre problème, mais il peut aider quelqu'un d'autre.

+0

Fait quelques changements supplémentaires. Une validation est coûteuse, de sorte que la clé d'une bonne performance est de choisir une fréquence de validation qui équilibre le coût de la validation par rapport à la surcharge de la transaction pendant trop longtemps. – DavidG

+0

Après d'autres changements, j'ai réussi à réduire le temps d'exécution de 19 minutes à 51 secondes en utilisant des transactions. – DavidG

+0

+1 Excellent, merci David! En fait, je ne peux pas me rappeler maintenant si j'ai essayé des transactions ou non, quand vous dites à travers le réseau que vous voulez dire à travers un réseau local, ou sur Internet? –

Questions connexes