Amélioration du temps d'importation mysql-dbase

pascalrochon Messages postés 18 Date d'inscription lundi 15 avril 2002 Statut Membre Dernière intervention 3 mars 2010 - 10 févr. 2007 à 17:30
pascalrochon Messages postés 18 Date d'inscription lundi 15 avril 2002 Statut Membre Dernière intervention 3 mars 2010 - 11 févr. 2007 à 22:34
Bonjour, je viens d'installer Mysql car j'ai maintenant un besoin de cré de très grosse base (au moin 40gig) à partir de petit fichier dbase (dbf) (environ 2000).


Suite a une recherche sur code source et autre site web j'ai construit une petite application me permettant d'importer en batch ma série de fichier dbf dans une table mysql. Mais voila le problème c'est que je trouve l'importation très longue.


Voici donc ce que j'utilise:


deux connexion ADO, une pour mysql et une pour Dbase,  ensuite je lit chacune des données et je les ajoute dans la base mysql. Voici donc la partie de mon programme qui importe les données


Set rs_mysql = New Recordset
Set rs_dbf = New Recordset
rs_mysql.Open "SELECT * FROM attribut;", conn_mysql, adOpenDynamic, adLockOptimistic
rs_dbf.Open "SELECT * FROM " & nom_dbf & ";", conn_dbf
rs_dbf.MoveFirst
Do Until rs_dbf.EOF
    rs_mysql.AddNew
    For Each fld In rs_dbf.Fields
        rs_mysql(fld.Name) = fld.Value    
    Next
    rs_dbf.MoveNext
    rs_mysql.Update
Loop

Est-ce qu'il y aurait une autre méthode ou bien une amélioration du code qui permettrait de fair l'importation plus rapidement? N'importe quel gains de temps sera appréciable car avec la quantité de table et de données que j'ai a importer ce sera apprécié.

Merci
Pascal

8 réponses

cs_casy Messages postés 7741 Date d'inscription mercredi 1 septembre 2004 Statut Membre Dernière intervention 24 septembre 2014 40
11 févr. 2007 à 14:43
Sans garantie de fonctionnement, tu peux peut-etre essayer une requette du style
INSERT INTO cible [(champ1[, champ2[,
...]])] [IN basededonnéesexterne]
    SELECT
[source.]champ1[, champ2[, ...]
    FROM
expressiontable

Depuis la table source pour chaque table, essaye la requette suivante :

INSERT INTO table_cible IN base_cible SELECT * FROM table_source

Bien sur il faut que les champs soient identiques et dans le même ordre dans les 2 tables. Sinon il faudra spécifier les différents champs dans la requette.

Je pense que ce style de requette fonctionne pour inserer tout les enregistrements d'une table en une seule passe. Il ne te reste plus qu'à boucler sur le nombre de table.

---- Sevyc64  (alias Casy) ----<hr size="2" width="100%" /># LE PARTAGE EST NOTRE FORCE #
0
pascalrochon Messages postés 18 Date d'inscription lundi 15 avril 2002 Statut Membre Dernière intervention 3 mars 2010
11 févr. 2007 à 17:17
Merci beaucoup ca semble très prometteur...

j'ai tenté plusieurs chose et je continue. mais ce que j'ai de la difficulté a comprendre c'est comment je prépare mes tables pour les inclures tout les deux dans une même requête, je m'explique:
 comme dit dans mon premier message j'utilise ADO, j'ai donc deux connexion (conn_dbf et conn_mysql) .
Set rs_dbf = New Recordset
rs_dbf.Open "SELECT * FROM table_source;", conn_dbf

J'ai donc maintenant mes données à importer dans un recordset

maintenant il s'agit d'écrire la requete que tu me propose, mais c'est là que je me cogne la tête
voici donc ce que je tente
sql_insert = "INSERT INTO table_cible IN base_cible
" & rs_dbf
Set rs_mysql = conn_mysql.Execute(sql_insert)
mais ceci ne fonctionne pas du tout, ce que je n'arrive pas a comprendre c'est comment avoir mes données à importer dans le recordset qui importera les données?

je vois que j'ai quelque difficultés a comprendre l'utilisation des recordset.

pouvez-m'aider ? je me sens quelque peut bloquer (c'est peut dire..)

Merci
Pascal

PS: je tente également un autre chemin soit de créer une très grande requete du genre:
INSERT INTO table_cible values (val_1,val_2, etc...), mais ce que j'ai peur c'est que certaine table_source peuvent être très grande, donc une erreur peut plus facilement s'y glisser.. que pensez-vous de cette façon de faire?
0
cs_casy Messages postés 7741 Date d'inscription mercredi 1 septembre 2004 Statut Membre Dernière intervention 24 septembre 2014 40
11 févr. 2007 à 17:55
Perso j'aurais fait un code comme celui-ci :
testé sur une de mes bases sur une seule table, ça semble marcher

Dim MaConnexion As ADODB.Connection
Dim MaCommande As ADODB.Command

Set MaConnexion =  New ADODB.Connection
MaConnexion.Provider = "Microsoft.Jet.oledb.4.0"
MaConnexion.Open ("Base de données
source")

Set MaCommande = New ADODB.Command
MaCommande.ActiveConnection = MaConnexion
    ' Partie à boucler pour chaque table
    MaCommande.CommandText = "INSERT INTO
table_source IN 'Base de données cible' SELECT * FROM
table_cible"
    MaCommande.Execute
    ' ....................................

Set MaCommande  = Nothing
MaConnexion.Close
Set MaConnexion = Nothing

Bien sur ici je ne traite qu'une table. Il faut rajouter la boucle, etc....

---- Sevyc64  (alias Casy) ----<hr size="2" width="100%" /># LE PARTAGE EST NOTRE FORCE #
0
cs_casy Messages postés 7741 Date d'inscription mercredi 1 septembre 2004 Statut Membre Dernière intervention 24 septembre 2014 40
11 févr. 2007 à 17:57
Pardon, excuse moi, il faut inverser table_source et table_cible dans le code que j'ai donné.
"INSERT INTO table_cible IN 'Base de données cible' SELECT * FROM table_source"

---- Sevyc64  (alias Casy) ----<hr size="2" width="100%" /># LE PARTAGE EST NOTRE FORCE #
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_casy Messages postés 7741 Date d'inscription mercredi 1 septembre 2004 Statut Membre Dernière intervention 24 septembre 2014 40
11 févr. 2007 à 18:24
En imaginant que les tables existe déjà dans ta base cible et qu'elles portent exactement le même nom que dans la base source, tu pourrais faire une boucle de ce style par exemple :

    ' Partie à boucler pour chaque table
    Dim rstSchema As ADODB.Recordset
    Set rstSchema = MaConnexion.OpenSchema(adSchemaTables)
    Do Until rstSchema.EOF
        MaCommande.CommandText = "INSERT INTO
" & rstSchema!TABLE_NAME & " IN 'Base de données cible' SELECT * FROM " & rstSchema!TABLE_NAME
        MaCommande.Execute
        rstSchema.MoveNext
    Loop
    rstSchema.Close
    Set rstSchema = Nothing
    '
....................................

---- Sevyc64  (alias Casy) ----<hr size="2" width="100%" /># LE PARTAGE EST NOTRE FORCE #
0
pascalrochon Messages postés 18 Date d'inscription lundi 15 avril 2002 Statut Membre Dernière intervention 3 mars 2010
11 févr. 2007 à 21:30
Un grand merci,

j'y suis presque (enfin je pense et j'espère), il n'y a qu'une chose que je ne comprend pas très bien dans ton code, dans ta requete SQL tu as 'base de données cible', comment as-tu connecter cette base externe, parce que dans mon cas, les deux tables ne sont pas dans la même base, ni même sur le même format (dbase, mysql)

Ce que je comprend c'est que tu ouvre une connexion contenant la table à importer, ensuite tu la rend active et c'est à ce moment que tu execute ta commande sql, mais où est indiquer l'endroit où se trouve la base de données cible? c'est-à-dire la connexion à la base cible

Merci encore
Pascal
0
cs_casy Messages postés 7741 Date d'inscription mercredi 1 septembre 2004 Statut Membre Dernière intervention 24 septembre 2014 40
11 févr. 2007 à 21:54
Effectivement j'avais zappé les types de bases. Moi j'ai fais les tests avec des bases access

En fait, avec cette méthode, tu n'as pas de connection à ouvrir avec le base cible. C'est, à la place de Base de données cible, que tu dois mettre le chemin d'accès à la base cible. Ensuite c'est le moteur ADO qui se charge de faire la connection.

MAintenant, effectivement je ne sais pas ce qu'il faut mettre pour une base mysql. Certainement l'adresse du serveur mais la syntaxe ???

Si je peux, je vais essayer de faire le test avec une autre base.

---- Sevyc64  (alias Casy) ----<hr size="2" width="100%" /># LE PARTAGE EST NOTRE FORCE #
0
pascalrochon Messages postés 18 Date d'inscription lundi 15 avril 2002 Statut Membre Dernière intervention 3 mars 2010
11 févr. 2007 à 22:34
J'ai regardé ce que tu m'a dit dans ton dernier message et voici ce le résultats:
Dim MaCommande As ADODB.Command
Set rs_mysql = New Recordset
Set MaConnexion = New ADODB.Connection

chemin = "C:\pw outaouais\C_1"
MaConnexion.Open "Driver={Microsoft dBASE Driver (*.dbf)};DriverID=277;Dbq=" & chemin & ";"

connexion_mysql= "DRIVER={MySQL ODBC 3.51 Driver}; SERVER=serviteur; DATABASE=pw_outaouais; UID=user; PWD=password"
Set MaCommande = New ADODB.Command
MaCommande.ActiveConnection = MaConnexion
    MaCommande.CommandText = "INSERT INTO attribut IN '" & connexion_mysql & "' SELECT * FROM 13_40"
    MaCommande.Execute

Le message d'erreur que je recois: il me dit qu'il ne trouve pas le fichierC:\patchwork outaouais\C_1\DRIVER={MySQL ODBC 3.51 Driver}; SERVER=serviteur; DATABASE=pw_outaouais; UID=user; PWD=password

Ce que je comprend c'est que je n'utilise pas la bonne méthode de connexion pour la base cible, est-ce que tu as une idée?

Merci
Pascal
0
Rejoignez-nous