Mettre à jour table SQL rapidement. [Résolu]

Messages postés
33
Date d'inscription
lundi 28 juillet 2003
Dernière intervention
9 décembre 2013
- - Dernière réponse : Tolopax19
Messages postés
1
Date d'inscription
samedi 13 février 2010
Dernière intervention
13 février 2010
- 13 févr. 2010 à 08:11
Bonjour,

Celà fait quelques jours que je bute sur un problème sans trouver de solution.
Je suis en VB.net sous VS 2005.
Explications
J'ai beaucoup d'enregistrements à mettre à jour vers mon SQL à l'origine issu de base Access. Pour le moment je me suis concentré sur une seule table (client) car c'est la plus simple (différent des reservations par exemple qui elle implique des relations à d'autre tables).

J'essai de faire ses mises à jour le plus rapidement possible car j'aurais au final plusieurs tables pour plusieurs agences. Donc dans un premier temps j'ai chargé ma table de client Access (pour 1 agence), puis j'ai chargé ma table de "relation" (la table correspondante à la table client dans SQL s'appelle particulier) qui fait le lien entre 1 identifiant client et 1 identifiant particulier. Dans le but de retrouver le plus rapidement l'identifiant particulier pour un client, j'ai créer un dictionnaire.

J'ai ensuite récupéré dans un datatable mes particuliers (filtré sur l'agence), j'ai créé un dictionnaire basé sur le numéro de ligne dans le datatable et l'identifiant particulier pour m'éviter de passé par le rowfilter (trop couteux en temps) quand je dois aller mettre à jour mon enregistrement dans le datatable.

Dim dtableParticulier As DataTable =  New DataTable
Dim dicoIdx_dtableParticulier As Generic.Dictionary(Of Long, Long) = New Generic.Dictionary(Of Long, Long)

Dim reqUpd As String = "SELECT * FROM tParticulier WHERE idAgence=" & idAgence
Dim SDATempo As SqlClient.SqlDataAdapter = New SqlClient.SqlDataAdapter(reqUpd, WUCtParticulier.ChaineCnx)
SDATempo.Fill(dtableParticulier)

Dim nbEnrParticulier As Integer = dtableParticulier.Rows.Count
If nbEnrParticulier > 0 Then
For i As Integer = 0 To nbEnrParticulier - 1
    dicoIdx_dtableParticulier.Add(dtableParticulier.Rows(i)("idParticulier"), i)
Next
End If


Ensuite je parcours mon datatable client issus d'access, je regarde via mon dico si j'ai l'équivalent au client côté SQL, je fais des contrôles sur les données (type,contenu, etc) et :
1- Soit je créé directement l'enregistrement dans ma base SQL, récupére l'identifiant créé, ajoute la relation entre client et particulier en base
2- Soit je retrouve ma ligne à mettre à jour dans mon datatable de particulier, et j'y insére les nouvelles valeurs.

Puis au final, je "tente" de mettre le plus rapidement ma table particulier à jour ( c'est ici que j'ai mon problème de temps )

SDATempo.UpdateCommand  = New SqlClient.SqlCommandBuilder(SDATempo).GetUpdateCommand
SDATempo.Update(dtableParticulier)
SDATempo.Dispose()


C'est très long. Alors j'ai cherché sur le net et j'ai vu que l'on pouvait passé en transaction, mais pas moyen d'y arrivé, je tombe d'exception en exception.

Je vous remercie d'avance.
Vincent.
Afficher la suite 

Votre réponse

15 réponses

Meilleure réponse
Messages postés
33
Date d'inscription
lundi 28 juillet 2003
Dernière intervention
9 décembre 2013
3
Merci
Bonjour,

A l'heure qu'il est j'ai résolu mon problème, je peux toujours optimiser les autres parties que la mise à jour mais je ne pense pas que ce soit nécessaire, par rapport au gain.

Je vais donc expliquer les 2 méthodes que j'ai employé.

1ère méthode
But : profiter de la commande update généré, enlever le "surplus" et profiter des SqlParameters et enlever ici aussi le "surplus" et mettre moi même les valeurs dans les parametres.
La difficulté aura été pour les paramètres qu'on ne peut pas prendre et mettre ailleurs, d'où clonage et "stockage"

Dans un premier temps, j'ai transformé ma partie "update" en Sub pour avoir plus de visibiliter et pourquoi par l'utiliser dans d'autres cas.
Celui-ci demande un chaine de connexion, mon SqlDataAdapter (reférence), et mon datatable (référence)

   'Création automatique de la commande update à partir de la source
   SDA.UpdateCommand =  New SqlClient.SqlCommandBuilder(SDA).GetUpdateCommand

   'Récuperation de la commande et conservation du strict minimum
   Dim updCmd As String = SDA.UpdateCommand.CommandText
   Dim idx_where As Integer = updCmd.IndexOf("where", 0, StringComparison.CurrentCultureIgnoreCase)
   Dim strCmd As String = updCmd.Substring(0, updCmd.IndexOf(")", idx_where))
   While strCmd.LastIndexOf("(") > idx_where
      strCmd = strCmd.Remove(strCmd.LastIndexOf("("), 1)
   End While

  'Récuperation des paramètres de mise à jour créer util par rapport à la commande filtrée
  Dim lstParam As Generic.List(Of SqlClient.SqlParameter) = New Generic.List(Of SqlClient.SqlParameter)

  For Each p As SqlClient.SqlParameter In SDA.UpdateCommand.Parameters
     If strCmd.Contains(p.ParameterName) Then
        lstParam.Add(CType(CType(p, ICloneable).Clone, SqlClient.SqlParameter))
     End If
  Next

  cnx.Open()
  Using trans As SqlClient.SqlTransaction = cnx.BeginTransaction
      Using cmd As SqlClient.SqlCommand = cnx.CreateCommand
         cmd.CommandText = strCmd
         cmd.Transaction = trans

         For Each p As SqlClient.SqlParameter In lstParam
             cmd.Parameters.Add(p)
         Next

         Dim nbParam As Integer = cmd.Parameters.Count
         dtable.DefaultView.RowStateFilter = DataViewRowState.ModifiedCurrent
         For i As Integer = 0 To dtable.DefaultView.Count - 1
            For j As Integer = 0 To nbParam - 1
                cmd.Parameters.Item(j).Value = dtable.DefaultView(i)(cmd.Parameters.Item(j).SourceColumn)
            Next
         cmd.ExecuteNonQuery()
         Next
     End Using
     trans.Commit()
End Using
cnx.Close()


Ainsi pour 8368 enregistrements (dont 7897 mise à jour) je passe de mes précédentes méthodes de 5mins 21 à 2mins 23.

Après avoir vu la difficulté avec les sqlParameters, je me suis demandé comment les éviter. Simplement en remplacant directement les paramètres dans ma commande, mais en ajoutant quand il faut les aspostrophes.

Voici donc la seconde méthode utilisé (second sub en m'inspirant du 1er)

2ème méthode :

Changement mineur, pour avoir le nom des paramètres à la place de @p1,@p2... puis par la suite j'ai du retirer le @original_idParticulier de mon where

SDA.UpdateCommand  = New SqlClient.SqlCommandBuilder(SDA).GetUpdateCommand(True)
...
End While

'Recuperation des noms de colones
Dim lstColDtable As Generic.List(Of String) = New Generic.List(Of String)
For i As Integer = 0 To dtable.Columns.Count - 1
  lstColDtable.Add(dtable.Columns(i).ColumnName)
Next

cnx.Open()
Using trans As SqlClient.SqlTransaction = cnx.BeginTransaction
   Using cmd As SqlClient.SqlCommand = cnx.CreateCommand
         cmd.Transaction = trans
         strCmd = strCmd.Replace("@Original_", "@")

         Dim nbParam As Integer = cmd.Parameters.Count
         dtable.DefaultView.RowStateFilter = DataViewRowState.ModifiedCurrent
         For i As Integer = 0 To dtable.DefaultView.Count - 1
            cmd.CommandText = strCmd
              For j As Integer = 0 To lstColDtable.Count - 1
                 With cmd
                    If dtable.Columns(lstColDtable(j)).DataType.Name GetType(System.String).Name OrElse dtable.Columns(lstColDtable(j)).DataType.Name GetType(System.DateTime).Name Then
                      .CommandText = .CommandText.Replace("@" & lstColDtable(j), "'" & dtable.DefaultView(i)(lstColDtable(j).Replace("'", "''")) & "'")
                    Else
                      .CommandText = .CommandText.Replace("@" & lstColDtable(j), dtable.DefaultView(i)(lstColDtable(j)))
                    End If
                 End With
                 Next
                 cmd.ExecuteNonQuery()
              Next
   End Using
   trans.Commit()
End Using
cnx.Close()



Ainsi pour le même nombre de traitemnt que précédement, je suis passé à 24 secondes.
Par curiosité j'ai enlevé le filtre sur les clients (reservation et option) issu de la base access, ce qui me reviens à 17964 enregistrements dont 16978 à mettre à jour. J'ai mis 47 secondes. Le plus impressionnant c'est que je n'ai pas perdu de temps dans mon update (mais gagné, surement dû à l'état du serveur SQL à ce moment là). J'en ai perdu sur le reste (lecture depuis access, ajout des enregistrements dans SQL)

Bref au final je passe de mes 12 mins 38 (48 mins 40 de ma collègue qui faisait un update entier de la table access vers SQL avant de faire ses traitements) à mes 47 secondes.


Voilà, merci de votre aide, si vous avez des questions ou suggestions.

Merci conan76 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources a aidé 97 internautes ce mois-ci

Commenter la réponse de conan76
Messages postés
14010
Date d'inscription
samedi 29 décembre 2001
Dernière intervention
28 août 2015
0
Merci
Salut
Les Transactions permettent de stocker une série de commande et de les exécuter d'un seul coup.
Le gain de temps sera donc lié à l'ouverture unique d'un canal vers ta base et une meilleure gestion des buffers. Elles offrent aussi un avantage dans la gestion multi-utilisateurs.

Les Transactions s'appliquent au niveau de la connexion à ta DB.
Je n'ai pas de syntaxe à te proposer, ne connaissant pas ces méthodes .Net.

Ca commence par maConnexion.BeginTrans
Suivi de plusieurs instructions.
Quand tu veux les exécuter : maConnexion.CommitTrans
Si tu voulais annuler et ne pas exécuter : maConnexion.RollbackTrans

Vala
Jack, MVP VB
NB : Je ne répondrai pas aux messages privés

Le savoir est la seule matière qui s'accroit quand on la partage (Socrate)
Commenter la réponse de cs_Jack
Messages postés
33
Date d'inscription
lundi 28 juillet 2003
Dernière intervention
9 décembre 2013
0
Merci
Merci, je viens de passer mon code avec les transactions,mais j'obtiens le même temps, il doit donc y avoir une erreur.

 SDATempo.UpdateCommand = New SqlClient.SqlCommandBuilder(SDATempo).GetUpdateCommand
 SDATempo.UpdateCommand.Connection.Open()
 SDATempo.UpdateCommand.Transaction = SDATempo.UpdateCommand.Connection.BeginTransaction
 tpsUpd.Start()
 SDATempo.Update(dtableParticulier)
 SDATempo.UpdateCommand.Transaction.Commit()
 tpsUpd.Stop()
 SDATempo.UpdateCommand.Connection.Close()
 SDATempo.Dispose()


pour le moment je ne travail que sur une agence/une table (filtrée sur les clients actif) sachant que j'ai des plus grosses tables à mettre à jour plus complexe. 12 autres tables "principales" et que j'aurais 13 agences ainsi. Le traitement étant fait tout les 15 jours.

Le temps ici pour l'update est de 310697ms (5mins11) (pour 7897 enregistrements à mettre à jour) le temps total de la fonction "client" étant de 5mins29.
Autant dire que mon goulot d'étranglement est ici. Ce qui me fait peur c'est le temps total sur l'ensemble des agences.

C'est pourquoi j'ai besoin d'aide.Merci.
Commenter la réponse de conan76
Messages postés
14010
Date d'inscription
samedi 29 décembre 2001
Dernière intervention
28 août 2015
0
Merci
Plus de 5 minutes pour 8000 enregistrements : en effret, ça rame dur !
Il y a un autre problème, ce n'est pas normal.
Concernant l'utilisation des Transactions : Oui, si tu ne fais qu'une seule opération entre le Begin et le Commit, il n'y a aucune raison que cela soit plus rapide.
Cette technique n'est intéressante que si tu as une vingtaine/centaine de petites requètes à traiter en une fois.
Si ta requète est trop grosse, c'est peut-être un problème d'organisation de tes Tables (trop grosses tables, répétition des données) et/ou la gestion des indexations des Tables (manquants pour les Champs avec lesquels tu fais des recherches)

D'autre part, vérifie le paramétrage de ... quelle est la source de données, au fait ? Access, SQL Server ?
DB locale ou par réseau ? par internet ?
- Pas assez de mémoire sur la machine
- Espace disque limite saturation
- Fragmentation disque
- Puissance processeur (pour une DB, c'est surtout la vitesse qui jouera, pas de grosse différence entre un Intel P ou un Celeron + pas persuadé que Access ou SQL Server sache exploiter le nombre de coeurs)

Vala
Jack, MVP VB
NB : Je ne répondrai pas aux messages privés

Le savoir est la seule matière qui s'accroit quand on la partage (Socrate)
Commenter la réponse de cs_Jack
Messages postés
33
Date d'inscription
lundi 28 juillet 2003
Dernière intervention
9 décembre 2013
0
Merci
Bonjour,

Merci de m'aider à la résolution de mon problème.

Voici ce que je peux dire, le temps qu'un collègue du service "matériel" me renseigne.
le VS2005 de ce projet tourne sur une machine virtuelle (car s'il doit être lancé tout les 15 jours c'est plus simple et ne nous dérange pas dans notre travail) la machine virtuelle à 3 instances. les autres instances sont actives (windows tourne) mais n'ont pas de tâches.

Config machine viruelle
Intel xeon 3040 dualcore @ 1.86Ghz, 2Go Ram

Config de l'instance sur laquelle je travail de la Machine virtuelle :
Intel xeon 3040 @ 1.86Ghz
Ram : 512

Le serveur SQL (prototype, je ne travaille heureusement pas sur la production) possède 2 instances SQL, mets seul l'une d'elle est utilisé régulièrement.
L' autre instance étant pour nos formations

La machine physique est un 2x Intel Xeon 1.8Ghz avec 4Go Ram.

la base source access est sur le poste virtuelle (récupération des agences la nuit), mais ce n'est pas elle qui est en cause car c'est au moment de l'update et donc du datatable vers SQL server

pour info même si j'ai mis les transactions dans mon code, post précédent c'est l'update du SDA qui tourne. Donc cela signifie que l'activation des transaction ici ne sert à rien.

les SQL serveur est sur le réseau (local) le ping est donc très bas (vérifié)
Commenter la réponse de conan76
Messages postés
14010
Date d'inscription
samedi 29 décembre 2001
Dernière intervention
28 août 2015
0
Merci
Eh beh, organisation complexe.
Si ta machine virtuelle (quel Windows ?) tourne avec 512 Mo de mémoire : Normal qu'elle soit lente.
Avec 2Go de mémoire sur la machine hôte, tu peux pousser jusqu'à 800 ou 900 Mo pour ta machine virtuelle - jette un oeil à la quantité mémoire restante dans le gestionnaire des tâches quand cette machine virtuelle est chargée.
Même si rien ne tourne sur les autres machines virtuelles, elles consomment de la mémoire.
"l'activation des transaction ici ne sert à rien" : Tu as surement raison, je ne connais pas assez .Net pour te répondre.

D'une manière générale, il est moins gourmand en mémoire de faire 10.000 "Insert Into" individuels que de charger une table entière en mémoire et d'y ajouter tes données. C'est une question d'organisation et, hélas, .Net précaunise l'utilisation des DataTable alors qu'un bon vieux RecordSet et des "Insert Into" est plus performant (avec Transaction).

Si ce programme ne tourne que tous les 15 jours, pourquoi es-tu pressé ? Tu n'es plus à 1/4 d'heure prêt, lol ...

Désolé, je suis à court d'idée.

Vala
Jack, MVP VB
NB : Je ne répondrai pas aux messages privés

Le savoir est la seule matière qui s'accroit quand on la partage (Socrate)
Commenter la réponse de cs_Jack
Messages postés
2859
Date d'inscription
mardi 15 avril 2003
Dernière intervention
26 novembre 2013
0
Merci
Salut,

Je ne veux pas dire de bétises mais... Si j'ai bien compris...

Tu récupère les données de la nouvelle table que tu place dans un DataTable.

En suite tu modifies cette table virtuelle, selon les données de la table access et tu update cette table vers la base SQL ?

Pourquoi ne pas travailler lignes par lignes :

Boucle

- Récupération de la ligne X dans la nouvelle base
- Récupération de la ligne X dans l'ancienne base
- Comparaison des deux lignes...
- Si la ligne est modifié Requête Update vers la nouvelle base
- Sinon on passe à la ligne suivante

Fin de boucle

De cette façon tu évite de mettre à jour des lignes qui n'ont pas été modifié. Certes tu auras pour 8 000 lignes 16 000 requêtes SELECT mais la lecture est toujours plus rapide que l'écriture.

Je dis peut être des bétises mais... On ne sait jamais...

Si le déboguage est l'art d'enlever les bogues, la programmation doit être l'art de les créer.
Commenter la réponse de Mayzz
Messages postés
33
Date d'inscription
lundi 28 juillet 2003
Dernière intervention
9 décembre 2013
0
Merci
Merci pour votre aide, je répondrais ensuite et donnerais quelques eclaircissement.
J'ai fais des test avec une personne du service "matériel" qui lui a l'accès au serveur SQL.

voici ce que l'on a fait :
- test depuis le poste virtuel et on scrute le gestionnaire de tâche du serveur SQL : on voit sur les 4 représentations processeur (rappel c'est 2 processeurs en hyperthreading) on voit l'appel au 4ème CPU, pendant quelques instant (surement récupération des tâches à faire pour les SQL) puis le CPU4 passe à 0% et le CPU3 enchaine à 100% durant les 5 mins.

Par curiosité j'ai ensuite récupérer le projet sur mon poste (machine avec plus de ram) pour remplacer le poste virtuel.

on a relevé la même chose, et en plus j'ai pu "voir" les données arrivé (car pic) sur la carte réseau du serveur SQL. puis retour (pic) après les 5 mins

idem donc ce n'est pas le poste du projet qui est en cause.

On va voir si on peut suivre l'instance SQL via le moniteur de performance.
Je vais refaire une purge de mes bases etc... avant de refaire mon import (je dois approchés les 100 "purges" et remise en état depuis le début de semaine.)

nota : les pics réseaux sont court donc ce n'est pas non plus réseau.
Commenter la réponse de conan76
Messages postés
14010
Date d'inscription
samedi 29 décembre 2001
Dernière intervention
28 août 2015
0
Merci
Rappel : Virtual PC ne fonctionne que sur un seul processeur.
Quels OS ?
Commenter la réponse de cs_Jack
Messages postés
2859
Date d'inscription
mardi 15 avril 2003
Dernière intervention
26 novembre 2013
0
Merci
L'inconvéniant avec le managé c'est que l'on ne sait jamais ce qui se cache derière !

La méthode Update du TableAdapter oblige surement le serveur à traiter les nouvelle données (ne mettre à jour que les nouvelles ligne) en lui envoyant le paquet de données.

Si tel est le cas, il y a biensur une surcharge de traitement au niveau du serveur qui ne sert à rien ! il en va de même pour le réseau, des données non traités sont envoyés vers le serveur. Essaye la méthode plus haut.

Si le déboguage est l'art d'enlever les bogues, la programmation doit être l'art de les créer.
Commenter la réponse de Mayzz
Messages postés
33
Date d'inscription
lundi 28 juillet 2003
Dernière intervention
9 décembre 2013
0
Merci
Pour info, j'ai repris le projet de quelqu'un car l'ensemble des mises à jours prenait 1 semaine. J'ai beaucoup réduit le temps rien que sur la mise à jour des clients.
49min à 10min30 pour environ 18000 enregistrements. Puis vu avec mon responsable, on ne prends pour le moment que les clients ayant un certain état dans ma table source.
du coup moins d'enregistrements en source, gain en temps au global : 5 à 6mins

Je suis d'accord que l'update via SDA est plus lourd/long que des requêtes individuels, enfin faut voir car à chaque fois celà fait des accès réseaux plutôt qu'un "paquet".

J'ai tenté ce matin de mettre mes données en "multi-requêtes" pour l'envoi

  Dim sqlP As SqlClient.SqlParameter

  For i As Integer = 0 To dtableParticulier.Rows.Count
If dtableParticulier.Rows(i).RowState = DataRowState.Modified Then
        For Each sqlP In SDATempo.UpdateCommand.Parameters
            sqlP.Value = dtableParticulier.Rows(i)(sqlP.SourceColumn)
        Next
        SDATempo.UpdateCommand.ExecuteNonQuery()
   	End If
  Next


En fait je voulais reprendre la base de la requête généré par le GetUpdateCommand et inséré dans mes paramètre leur valeur depuis la base.

sauf que la requête update contient plus de paramètres que de colonnes (reprise dans un where, je ne comprends pas pourquoi)
UPDATE [tParticulier] SET [idTitreParticulier] = @p1, [strNomParticulier] = @p2, [strPrenomParticulier] = @p3, [strNomConjoint] = @p4, [strPrenomConjoint] = @p5, [strNomCourrier] = @p6, [strAdresse] = @p7, [strCP] = @p8, [strCI] = @p9, [strCommune] = @p10, [strTelPersonnel] = @p11, [strTelPortable] = @p12, [strTelTravail] = @p13, [strFax] = @p14, [strEmail] = @p15, [ltxtObservation] = @p16, [idSession] = @p17, [idAgence] = @p18, [dtEnrCrea] = @p19, [idUserEnrCrea] = @p20, [dtEnrModif] = @p21, [idUserEnrModif] = @p22, [idSwitchDataBase] = @p23 
WHERE (([idParticulier] = @p24) AND ((@p25 = 1 AND [idTitreParticulier] IS NULL) OR ([idTitreParticulier] = @p26)) AND ((@p27 = 1 AND [strNomParticulier] IS NULL) OR ([strNomParticulier] = @p28)) AND ((@p29 = 1 AND [strPrenomParticulier] IS NULL) OR ([strPrenomParticulier] = @p30)) AND ((@p31 = 1 AND [strNomConjoint] IS NULL) OR ([strNomConjoint] = @p32)) AND ((@p33 = 1 AND [strPrenomConjoint] IS NULL) OR ([strPrenomConjoint] = @p34)) AND ((@p35 = 1 AND [strNomCourrier] IS NULL) OR ([strNomCourrier] = @p36)) AND ((@p37 = 1 AND [strAdresse] IS NULL) OR ([strAdresse] = @p38)) AND ((@p39 = 1 AND [strCP] IS NULL) OR ([strCP] = @p40)) AND ((@p41 = 1 AND [strCI] IS NULL) OR ([strCI] = @p42)) AND ((@p43 = 1 AND [strCommune] IS NULL) OR ([strCommune] = @p44)) AND ((@p45 = 1 AND [strTelPersonnel] IS NULL) OR ([strTelPersonnel] = @p46)) AND ((@p47 = 1 AND [strTelPortable] IS NULL) OR ([strTelPortable] = @p48)) AND ((@p49 = 1 AND [strTelTravail] IS NULL) OR ([strTelTravail] = @p50)) AND ((@p51 = 1 AND [strFax] IS NULL) OR ([strFax] = @p52)) AND ((@p53 = 1 AND [strEmail] IS NULL) OR ([strEmail] = @p54)) AND ((@p55 = 1 AND [ltxtObservation] IS NULL) OR ([ltxtObservation] = @p56)) AND ((@p57 = 1 AND [idSession] IS NULL) OR ([idSession] = @p58)) AND ((@p59 = 1 AND [idAgence] IS NULL) OR ([idAgence] = @p60)) AND ((@p61 = 1 AND [dtEnrCrea] IS NULL) OR ([dtEnrCrea] = @p62)) AND ((@p63 = 1 AND [idUserEnrCrea] IS NULL) OR ([idUserEnrCrea] = @p64)) AND ((@p65 = 1 AND [dtEnrModif] IS NULL) OR ([dtEnrModif] = @p66)) AND ((@p67 = 1 AND [idUserEnrModif] IS NULL) OR ([idUserEnrModif] = @p68)) AND ((@p69 = 1 AND [idSwitchDataBase] IS NULL) OR ([idSwitchDataBase] = @p70)))

sauf que les paramètres après @p23 sont typé différement de mes colonnes, pourquoi je ne sais pas, j'ai donc eu une erreur de conversion Uint32 en string.

Je voudrais éviter de mettre moi même une requête update classique, parce que l'update via le SDA gère très bien les champs pouvant être à NULL.

Je crois qu j'en arriverais à ça pour juste faire un test.

> En suite tu modifies cette table virtuelle, selon les données de la table access et tu update cette table vers la base SQL
oui enfin, les champs qui se retrouve du côté SQL, sinon je crée.
Je ne compare pas le contenu champs par champs, car dans la logique c'est plus long. puis le jour où quelqu'un rajoute un champs...

> Certes tu auras pour 8 000 lignes 16 000 requêtes ...
non car j'ai récupéré les lignes par lots, et créer un dico dessus, ce qui fait que de ce côté c'est extremement rapide donc 8000 + 1.

nota : le datatable sais si la ligne d'enregistrement a subi un changement via un flag (je me suis d'ailleurs fait avoir en réécrivant exactement la même chose dans mon datatable) et en faisant mon update (j'avais pas purger) mon traitement global était arrivé à 29secondes (j'avais cru le gain grâce aux transactions)

>Rappel : Virtual PC ne fonctionne que sur un seul processeur.
Quels OS ?

oui le virtuel n'est que pour le poste projet (XP) mais ce n'est clairement pas lui qui est en cause.


> La méthode Update du TableAdapter oblige surement le serveur à traiter les nouvelle données (ne mettre à jour que les nouvelles ligne) en lui envoyant le paquet de données.
le paquet envoyé à SQL ne contient que les ligne flaguer "mettre à jour"

un calcul fait vite fait et vu grâce aux compteur de performance, j'avais une ligne "transaction" à 20 (donc 20 transaction/seconde, je pense) si je fais 8000/20 = 400 secondes
soit pas loin de mon temps d'update.

donc le problème vient du update ou des transactions SQL limité à 20 (si elle viennent de l'exterieur ??) car quand je fais un insert pour remettre ma sauvegarde de table c'est 93000 et 68000 en 3 secondes, via le concepteur SQL sous Visual studio.

Au passage: super sympa :
> Si le déboguage est l'art d'enlever les bogues, la programmation doit être l'art de les créer.
ca colle bien à ma collègue.
Commenter la réponse de conan76
Messages postés
2859
Date d'inscription
mardi 15 avril 2003
Dernière intervention
26 novembre 2013
0
Merci
=)

Oui effectivement tu as raison pour le TableAdapter, je vien de tester (avec 8000 lignes), mais cela provient peut être de tes requêtes filtrant les nulls car si il y a une surcharge coté serveur c'est bien que le traitement par SQL Server est long et non le traitement locale par la machine virtuelle ?

De plus, comme tu le dis, le TableAdapter filtre grace au flag (RowState), tu ne dois pas avoir tant de lignes que cela à mettre à jour, essaye simplement avec une requête update classique.

De toute façon si tes deux tables son basés sur un schéma identique, pourquoi vouloir éviter les Nulls ? De plus cela peut provoquer une erreur de données, car si l'application qui gère la table access insert une valeur nulle dans la table, la mise à jour via ton application n'insèrera pas cette valeur nulle et laissera la valeur courrante.


Si le déboguage est l'art d'enlever les bogues, la programmation doit être l'art de les créer.
Commenter la réponse de Mayzz
Messages postés
33
Date d'inscription
lundi 28 juillet 2003
Dernière intervention
9 décembre 2013
0
Merci
Bonsoir,

J'écris de chez moi...

En fait j'ai compté le nombre de lignes qui sont mis à jour dans ma boucle qui contrôle si l'enregistrement existe. et donc ici pas loin de 8000 update.
Je fait comme ceci et j'ai utilisé des stopwatch pour avoir le temps :

- Parcours les enregistrements access (datatable)
-- via dico, si enregistrement existe dans SQL (car mon dico contient identifiant access en clé et identifiant SQL en "value") me retourne identifiant, sinon -1 (temps : 0ms)
--- Si -1
---- nbAdd+=1
---- Ajouter nouvel enregistrement en base (insert : rapide, n'ayant pas besoin d'optimisation)
---- contrôle des champs (nothing,null,type, remplacement des apostrophes en 2 apostrophes, concaténation pour les champs existant en SQL mais pas en Access...)
---- Ajouter à ma table SQL liaison l'identifiant SQL qui vient d'être créé et l'identifiant access.
--- Sinon Si >0
---- nbUpd+=1
---- contrôle des champs (nothing,null,type, remplacement des apostrophes en 2 apostrophes, concaténation pour les champs existant en SQL mais pas en Access...)
---- ajout des modifications dans le datatable
- prochain enregistrement access

- Si nbUpd>0
-- mise à jours vers SQL
- FinSi

je dois faire mon add à part car je dois créer l'enregistrement "liaison" basé sur la clé qui vient d'être faite.
je confirme que c'est le traitement côté SQL qui est long.

La table source n'est pas identique à la table destination
1) champs identique ou différent (ex : fusion de champs texte)
2) champs en plus (date d'enregistrement,identifiant utilisateur qui a ajouté l'enregistrement...)
3) champs non renseigné dans access (pas à null mais "")

l'application access à l'origine de la table est plus permissive d'où des contrôles exemple : des codes postaux à plus de 5 chiffres ou simplement

> tu as raison pour le TableAdapter, je viens de tester (avec 8000 lignes)
tu as le même genre de temps que moi ?

Sinon j'ai posté sur le forum MSDN cette après midi étant membre MSDN j'espère avoir une réponse.
J'aimerais bien voir ce que le SQL reçoit à traiter par visual ainsi je pourrais peut-être le renvoyé via le concepteur de requêtes. et voir le temps.

Lundi si je peux je tenterais de faire les updates en boucle, mais ce n'est pas sûr car je dois repartir sur l'un de mes projets à finir avant mise en pilote et production. Je dois traiter ce projet de mise à jour en "tâche de fond" mais si je m'acharne dessus c'est qu'il commence à m'énerver car si cette lenteur est résolu alors les autres tables partiront sur le même principe de mise à jour, le plus gros étant fait, et ce sera quelque chose de "correcte" On y est presque...

En tout cas, merci pour l'aide et de voir que je ne pose pas ma question sans avoir cherché au préalable.
Commenter la réponse de conan76
Messages postés
33
Date d'inscription
lundi 28 juillet 2003
Dernière intervention
9 décembre 2013
0
Merci
Je viens d'avoir une idée à tester rapidement lundi :

reprendre la requete généré par le GetUpateCommand (UPDATE [tParticulier] SET [idTitreParticulier] = @p1, )
enlevé la partie après le where, y ajouter après idParticulier= @idParticulier
et faire le remplacement dans la boucle par le champs du même nom dans ma table.

car ce qui me gêne c'est le typage "bizarre" des champs dans mon where par le générateur de paramètres

puis je pourrais faire mon SDATempo.UpdateCommand.ExecuteNonQuery()

je verrais déjà le temps et aussi si mes données semblent bonnes en base puis voir ensuite les transactions.
surtout c'est voir si le temps de traitement par sql serveur et le même.

voilà
Commenter la réponse de conan76
Messages postés
1
Date d'inscription
samedi 13 février 2010
Dernière intervention
13 février 2010
0
Merci
Bonjour à tous,

J'aimerais juste savoir comment intégrer une fonction ou une procédure de vb6 dans une requête sql (Jointure de table)

Exemple :

SqL = "SELECT Table1.A1, Table2.B1, Carree(Table1.A1, Table2.B1) as REPONSE ....

Merci d'avance
Commenter la réponse de Tolopax19

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.