OVH Cloud OVH Cloud

Insertion dans une base SQLServer.

8 réponses
Avatar
Jerome
Salut à tous,

J'ai une application qui fait des INSERT dans une base SQLServer distante de
données issues d'un fichier Excel.

Pour 2053 données ça prend 7 minutes.
Pour 7660 données ça prend 20 minutes.
Et pour 65000 données ça prend près de 2 heures.

Les fichiers excel font respectivement 378Ko, 3,3Mo et 14,5Mo.

1. D'après-vous est-normal ????? Je cherche comment optimiser l'insertion
pour que ça mette moins de temps.
2. Si plusieurs personnes importent en même temps ça ralenti terriblement
l'importation (et pourtant les ressources du serveur sont correctes, maxi 5%
des procs).

Jérôme

8 réponses

Avatar
balmeyer
Non, pour moi ce n'est pas normal !
C'est peut-être la lecture du fichier Excel qui est lente (mais à ce
point ?), parce que quelques milliers d'insert, ça prend une minute,
pas plus.
Tu peux donner un extrait de ton code ?
Avatar
Jerome
> C'est peut-être la lecture du fichier Excel qui est lente (mais à ce point
?),



Non c'est instantané de ce côté là.

parce que quelques milliers d'insert, ça prend une minute, pas plus.



Tout dépend du poids des données (bon dans notre cas ça dépasse pas 300
octets au maximum), du nombre d'utilisateurs (y en a 4 au maximum qui
utilise le soft en même temps) et de la connexion (ils utilisents une
connexion à 512Kbps avec un lien montant de 128Kbps).

Tu peux donner un extrait de ton code ?



En fait c'est un simple Command qui utilise une requête INSERT et exécuté
via un ExecuteNonQuery, le tout englobé dans une transaction.

Voilà un bout du code qui construit et execute la requête :

For Each ln In node.link
Dim qryStr As String = "INSERT INTO tblInformations(IdCatalogue"
Dim values As String = "VALUES (" & node.id
Dim i As Integer

For i = 0 To ln.count - 1
If ln.Propriete(i) <> "" Then
qryStr &= ",strPropriete" & (i + 1)
values &= "," & IIf(ln.Propriete(i) = "", "NULL", "'" &
ln.Propriete(i).Replace("'", "''") & "'")
End If
Next
Dim command As New SqlCommand(qryStr & ") " & values & ");",
m_connection, m_transaction)
command.CommandTimeout = 0
command.ExecuteNonQuery()
Next
Avatar
Patrice
3 pistes à explorer selon le besoin et les contraintes :

1) Utiliser SqlBulkCopy en 2.0 (ou SqlXML 3.0 si 1.1)

2) Envoyer le fichier Excel et le traiter côté serveur (via OLEDB)

3) Sinon envoyer plusieurs insert en même temps ? Requête préparée avec
paramètres ?

A priori la solution 1 est vraiment très rapide...

Autres...

--
Patrice

"Jerome" a écrit dans le message de
news:
Salut à tous,

J'ai une application qui fait des INSERT dans une base SQLServer distante


de
données issues d'un fichier Excel.

Pour 2053 données ça prend 7 minutes.
Pour 7660 données ça prend 20 minutes.
Et pour 65000 données ça prend près de 2 heures.

Les fichiers excel font respectivement 378Ko, 3,3Mo et 14,5Mo.

1. D'après-vous est-normal ????? Je cherche comment optimiser l'insertion
pour que ça mette moins de temps.
2. Si plusieurs personnes importent en même temps ça ralenti terriblement
l'importation (et pourtant les ressources du serveur sont correctes, maxi


5%
des procs).

Jérôme




Avatar
balmeyer
Peut-être la concaténation des chaînes fait perdre du temps ?? Je ne
pense pas que ça soit là le principal facteur de lenteur, mais au
lieu d'utiliser l'opérateur &=, qui créé un nouvel objet string à
chaque fois, tu peux peut-être employer un objet StringBuilder :

- tu le créé avant la boucle.
- au début de chaque itération, tu appeles la méthode .Clear() pour
vider la chaine
- tu ajoutes chaque valeur (sans opérateur de concaténation & pour
VB) avec la méthode Append()

stringBuilder.Append("INSERT INTO tblInformations(IdCatalogue")
stringBuilder.Append("VALUES (")
stringBuilder.Append(",strPropriete")

- et tu récupére ta requête avec .toString()

Peut-être ne faut-il pas aussi créer un objet commande à chaque
itération, mais juste faire :

command.CommandText = stringBuilder.ToString()
command.ExecuteNonQuery()

En fait, l'idée est d'éviter la création de nouvelles références,
ce qui consomme pas mal de temps, je crois. Voilà, une modeste
contribution ! :)
Avatar
Jerome
Merci je vais regarder... cependant le problème est vraiment au niveau de
l'insertion...
Avatar
Jerome
Je ne connais pas SqlBulkCopy. Je vais regarder merci !

Jérôme
Avatar
Patrice Manac'h
Bonjour,

vous faîtes l'insertion en mode transactionnel ? Vous avez peut-être des
locks au niveau SQL. Pendant l'insert, si vous regardez dans l'outil
Enterprise Manager les locks, voyez vous quelque chose ?

Cdt,

P. Manac'h
MCS France

"Jerome" a écrit dans le message de news:

Merci je vais regarder... cependant le problème est vraiment au niveau de
l'insertion...




Avatar
The Ploum
Bonjour Jérôme,

Ta connexion "m_connection" est-elle ouverte avant d'entrer dans la boucle ?
Si ce n'est pas le cas, il faudrait que tu ouvre explicitement la connexion
avant d'entrer dans la boucle, et que tu la referme en sortie. Car sinon ADO
ouvre une connexion puis la referme à chaque itération !

Ploum

"Jerome" a écrit :

Salut à tous,

J'ai une application qui fait des INSERT dans une base SQLServer distante de
données issues d'un fichier Excel.

Pour 2053 données ça prend 7 minutes.
Pour 7660 données ça prend 20 minutes.
Et pour 65000 données ça prend près de 2 heures.

Les fichiers excel font respectivement 378Ko, 3,3Mo et 14,5Mo.

1. D'après-vous est-normal ????? Je cherche comment optimiser l'insertion
pour que ça mette moins de temps.
2. Si plusieurs personnes importent en même temps ça ralenti terriblement
l'importation (et pourtant les ressources du serveur sont correctes, maxi 5%
des procs).

Jérôme