OVH Cloud OVH Cloud

Performances de la clause "IN"

5 réponses
Avatar
Olivier
Je d=E9sire connaitre les limitations d'une clause "IN" :
SELECT * FROM MyTable WHERE MyField IN (...)

En pratique, je re=E7ois (de VB) un tableau d'=E9l=E9ments (->=20
2500) que j'ins=E8re dans une table temporaire (par=20
l'interm=E9diaire d'une boucle et d'un recordset=20
d=E9connect=E9 ; le traitement de la boucle est rapide mais=20
l'op=E9ration de mise =E0 jour (UpdateBatch) est assez longue).
Une fois cette table temporaire peupl=E9e, je r=E9alise=20
diverses action de mise =E0 jour de cette table temporaire =E0=20
partir de donn=E9es contenues dans d'autres tables.
Lorsque tous les traitements utiles ont =E9t=E9 r=E9alis=E9s,=20
j'ouvre un recordset bas=E9 sur cette table temporaire et je=20
renvoie l'info. en r=E9ponse au client.

Mon objectif est d'=E9viter ce traitement "lourd" en=20
utilisant, si possible, une clause "IN" qui contiendrait=20
les +/- 2500 =E9l=E9ments du tableau.

Est-ce possible ? Quelles sont les performances ?

5 réponses

Avatar
Fred BROUARD
Tu peut toujours faire une sous requête avec une clause IN

Exemple :
SELECT ....
FROM ...
WHERE UneColonne IN (SELECT ...
FROM MaTableTemp)

Dans ce cas il est intéressant de placer un index sur les colonnes en
relation dans le IN...

A +

Olivier a écrit:
Je désire connaitre les limitations d'une clause "IN" :
SELECT * FROM MyTable WHERE MyField IN (...)

En pratique, je reçois (de VB) un tableau d'éléments (->
2500) que j'insère dans une table temporaire (par
l'intermédiaire d'une boucle et d'un recordset
déconnecté ; le traitement de la boucle est rapide mais
l'opération de mise à jour (UpdateBatch) est assez longue).
Une fois cette table temporaire peuplée, je réalise
diverses action de mise à jour de cette table temporaire à
partir de données contenues dans d'autres tables.
Lorsque tous les traitements utiles ont été réalisés,
j'ouvre un recordset basé sur cette table temporaire et je
renvoie l'info. en réponse au client.

Mon objectif est d'éviter ce traitement "lourd" en
utilisant, si possible, une clause "IN" qui contiendrait
les +/- 2500 éléments du tableau.

Est-ce possible ? Quelles sont les performances ?



--
Frédéric BROUARD - expert SQL, spécialiste : SQL Server / Delphi / web
Livre SQL - col. Référence : http://sqlpro.developpez.com/bookSQL.html
Le site du SQL, pour débutants et pros : http://sqlpro.developpez.com
****************** mailto: ******************
Avatar
Fred M
Salut

Dans ton cas de figure il est souvent possible de
substituer une sous-req IN par une équijointure

SELECT MyTable.*
FROM MyTable, #TableTmp
WHERE MyTable.MyField = #TableTmp.AutreField

Tu y gagneras NETTEMENT en performance.
Cela dit, comme l'indique l'autre Fred, tu as grand
intéret à poser un index (non ordonné de préférence) sur
le champ MyField

-----Message d'origine-----
Je désire connaitre les limitations d'une clause "IN" :
SELECT * FROM MyTable WHERE MyField IN (...)

En pratique, je reçois (de VB) un tableau d'éléments (->
2500) que j'insère dans une table temporaire (par
l'intermédiaire d'une boucle et d'un recordset
déconnecté ; le traitement de la boucle est rapide mais
l'opération de mise à jour (UpdateBatch) est assez


longue).
Une fois cette table temporaire peuplée, je réalise
diverses action de mise à jour de cette table temporaire


à
partir de données contenues dans d'autres tables.
Lorsque tous les traitements utiles ont été réalisés,
j'ouvre un recordset basé sur cette table temporaire et


je
renvoie l'info. en réponse au client.

Mon objectif est d'éviter ce traitement "lourd" en
utilisant, si possible, une clause "IN" qui contiendrait
les +/- 2500 éléments du tableau.

Est-ce possible ? Quelles sont les performances ?
.



Avatar
Olivier
Merci pour l'info.

Dans mon cas, le problème vient du fait que la liste des
données à placer dans la clause "IN" est, à la base, un
tableau (array) fourni par VB.
J'ai effectivement créé une table temporaire dans laquelle
j'insère (par boucle + recordset déconnecté) le contenu du
tableau mais la fonction ADO "UpdateBatch" prend trop de
temps (+/- 50 sec. pour une insertion de 15.000 lignes, je
sais que ce n'est pas énorme mais j'ai vraiment besoin
d'optimiser les perf.).

Ex. (de mémoire) dans Visual Basic (ADO) :

For lngLoop = 0 To Ubound(MyArray)
MyRst.Add
MyRst.Fields(0).Value = MyArray(lngLoop)
MyRst.Fields(1).Value = "Sequence"
Next

...

MyRst.UpdateBatch

La boucle ne prend pas beaucoup de temps (manip. des
données en mémoire uniquement).
Par contre la fonction "UpdateBatch" (écriture dans la BD
via le réseau) prend +/- 50 sec.

Une fois les données insérées, j'utilisais des
fonctions "UPDATE MyTable SET ... FROM MyTable A LEFT
OUTER JOIN MyTable1 B ON A.MyField = B.MyField ...
WHERE ..."

-----Original Message-----
Salut

Dans ton cas de figure il est souvent possible de
substituer une sous-req IN par une équijointure

SELECT MyTable.*
FROM MyTable, #TableTmp
WHERE MyTable.MyField = #TableTmp.AutreField

Tu y gagneras NETTEMENT en performance.
Cela dit, comme l'indique l'autre Fred, tu as grand
intéret à poser un index (non ordonné de préférence) sur
le champ MyField

-----Message d'origine-----
Je désire connaitre les limitations d'une clause "IN" :
SELECT * FROM MyTable WHERE MyField IN (...)

En pratique, je reçois (de VB) un tableau d'éléments (->
2500) que j'insère dans une table temporaire (par
l'intermédiaire d'une boucle et d'un recordset
déconnecté ; le traitement de la boucle est rapide mais
l'opération de mise à jour (UpdateBatch) est assez


longue).
Une fois cette table temporaire peuplée, je réalise
diverses action de mise à jour de cette table temporaire


à
partir de données contenues dans d'autres tables.
Lorsque tous les traitements utiles ont été réalisés,
j'ouvre un recordset basé sur cette table temporaire et


je
renvoie l'info. en réponse au client.

Mon objectif est d'éviter ce traitement "lourd" en
utilisant, si possible, une clause "IN" qui contiendrait
les +/- 2500 éléments du tableau.

Est-ce possible ? Quelles sont les performances ?
.



.



Avatar
Fred BROUARD
créé un fichier texte et insert le d'un seul coup dans ta table
temporaire à l'aide de Bulk Insert.

A +

Olivier a écrit:
Merci pour l'info.

Dans mon cas, le problème vient du fait que la liste des
données à placer dans la clause "IN" est, à la base, un
tableau (array) fourni par VB.
J'ai effectivement créé une table temporaire dans laquelle
j'insère (par boucle + recordset déconnecté) le contenu du
tableau mais la fonction ADO "UpdateBatch" prend trop de
temps (+/- 50 sec. pour une insertion de 15.000 lignes, je
sais que ce n'est pas énorme mais j'ai vraiment besoin
d'optimiser les perf.).

Ex. (de mémoire) dans Visual Basic (ADO) :

For lngLoop = 0 To Ubound(MyArray)
MyRst.Add
MyRst.Fields(0).Value = MyArray(lngLoop)
MyRst.Fields(1).Value = "Sequence"
Next

...

MyRst.UpdateBatch

La boucle ne prend pas beaucoup de temps (manip. des
données en mémoire uniquement).
Par contre la fonction "UpdateBatch" (écriture dans la BD
via le réseau) prend +/- 50 sec.

Une fois les données insérées, j'utilisais des
fonctions "UPDATE MyTable SET ... FROM MyTable A LEFT
OUTER JOIN MyTable1 B ON A.MyField = B.MyField ...
WHERE ..."


-----Original Message-----
Salut

Dans ton cas de figure il est souvent possible de
substituer une sous-req IN par une équijointure

SELECT MyTable.*



FROM MyTable, #TableTmp



WHERE MyTable.MyField = #TableTmp.AutreField

Tu y gagneras NETTEMENT en performance.
Cela dit, comme l'indique l'autre Fred, tu as grand
intéret à poser un index (non ordonné de préférence) sur
le champ MyField


-----Message d'origine-----
Je désire connaitre les limitations d'une clause "IN" :
SELECT * FROM MyTable WHERE MyField IN (...)

En pratique, je reçois (de VB) un tableau d'éléments (->
2500) que j'insère dans une table temporaire (par
l'intermédiaire d'une boucle et d'un recordset
déconnecté ; le traitement de la boucle est rapide mais
l'opération de mise à jour (UpdateBatch) est assez



longue).

Une fois cette table temporaire peuplée, je réalise
diverses action de mise à jour de cette table temporaire



à

partir de données contenues dans d'autres tables.
Lorsque tous les traitements utiles ont été réalisés,
j'ouvre un recordset basé sur cette table temporaire et



je

renvoie l'info. en réponse au client.

Mon objectif est d'éviter ce traitement "lourd" en
utilisant, si possible, une clause "IN" qui contiendrait
les +/- 2500 éléments du tableau.

Est-ce possible ? Quelles sont les performances ?
.




.









--
Frédéric BROUARD - expert SQL, spécialiste : SQL Server / Delphi / web
Livre SQL - col. Référence : http://sqlpro.developpez.com/bookSQL.html
Le site du SQL, pour débutants et pros : http://sqlpro.developpez.com
****************** mailto: ******************
Avatar
Olivier
C'est aussi la conclusion à laquelle je suis arrivé.

Merci et A+.

-----Original Message-----
créé un fichier texte et insert le d'un seul coup dans ta


table
temporaire à l'aide de Bulk Insert.

A +

Olivier a écrit:
Merci pour l'info.

Dans mon cas, le problème vient du fait que la liste




des
données à placer dans la clause "IN" est, à la base, un
tableau (array) fourni par VB.
J'ai effectivement créé une table temporaire dans




laquelle
j'insère (par boucle + recordset déconnecté) le contenu




du
tableau mais la fonction ADO "UpdateBatch" prend trop




de
temps (+/- 50 sec. pour une insertion de 15.000 lignes,




je
sais que ce n'est pas énorme mais j'ai vraiment besoin
d'optimiser les perf.).

Ex. (de mémoire) dans Visual Basic (ADO) :

For lngLoop = 0 To Ubound(MyArray)
MyRst.Add
MyRst.Fields(0).Value = MyArray(lngLoop)
MyRst.Fields(1).Value = "Sequence"
Next

...

MyRst.UpdateBatch

La boucle ne prend pas beaucoup de temps (manip. des
données en mémoire uniquement).
Par contre la fonction "UpdateBatch" (écriture dans la




BD
via le réseau) prend +/- 50 sec.

Une fois les données insérées, j'utilisais des
fonctions "UPDATE MyTable SET ... FROM MyTable A LEFT
OUTER JOIN MyTable1 B ON A.MyField = B.MyField ...
WHERE ..."


-----Original Message-----
Salut

Dans ton cas de figure il est souvent possible de
substituer une sous-req IN par une équijointure

SELECT MyTable.*



FROM MyTable, #TableTmp



WHERE MyTable.MyField = #TableTmp.AutreField

Tu y gagneras NETTEMENT en performance.
Cela dit, comme l'indique l'autre Fred, tu as grand
intéret à poser un index (non ordonné de préférence)






sur
le champ MyField


-----Message d'origine-----
Je désire connaitre les limitations d'une clause "IN" :
SELECT * FROM MyTable WHERE MyField IN (...)

En pratique, je reçois (de VB) un tableau d'éléments (-







2500) que j'insère dans une table temporaire (par
l'intermédiaire d'une boucle et d'un recordset
déconnecté ; le traitement de la boucle est rapide








mais
l'opération de mise à jour (UpdateBatch) est assez



longue).

Une fois cette table temporaire peuplée, je réalise
diverses action de mise à jour de cette table








temporaire

à

partir de données contenues dans d'autres tables.
Lorsque tous les traitements utiles ont été réalisés,
j'ouvre un recordset basé sur cette table temporaire








et

je

renvoie l'info. en réponse au client.

Mon objectif est d'éviter ce traitement "lourd" en
utilisant, si possible, une clause "IN" qui








contiendrait
les +/- 2500 éléments du tableau.

Est-ce possible ? Quelles sont les performances ?
.




.









--
Frédéric BROUARD - expert SQL, spécialiste : SQL Server /


Delphi / web
Livre SQL - col. Référence :


http://sqlpro.developpez.com/bookSQL.html
Le site du SQL, pour débutants et pros :


http://sqlpro.developpez.com
****************** mailto:


******************

.