|
Publicité ' | |||||||||||||||||||||||
|
|
#1 |
|
Invité de passage
![]() Développeur COBOL Inscription : août 2011 Messages : 3 ![]() |
Bonjour,
J'aimerai savoir comment optimiser les requêtes suivantes, qui génèrent des fullscan et ne sont pas très performantes. T1 : C1, C2, C3, C4, C5 Clé primiare C1 T2 : C6, C7 Clé primaire C6 Les 2 tables de possèdent pour le moment que les index sur les clés primaires. Requète 1: SELECT C1, C2, C3, C4, C5, C7 FROM T1, T2 WHERE C1 = C6 AND C2 = ? AND C3 LIKE ? AND C4 > ? AND C5 LIKE ? ORDER BY C2 ASC, C3 ASC, C7 ASC Requète 2: SELECT COUNT(*) INTO N FROM T1 WHERE C2 = ? AND C3 LIKE ? AND C4 > ? AND C5 LIKE ? |
|
|
00
|
|
|
#2 |
|
Membre actif
![]() Inscription : juin 2008 Messages : 146 ![]() |
Bonjour,
Les index actuels te permettent d'avoir une jointure optimisée mais tu pars en scan d'une des 2 tables. Le prédicat le meilleur, c'est celui sur C2. Donc si cette colonne est discriminante, un index sur cette colonne te donnera des temps de réponse ok. Si C2 n'est pas du tout discriminant, vérifie les statistiques de C3 et C5, un LIKE étant en général performant, sauf avec % en début de recherche du type LIKE '%DUPONT%'. La tu pars en scan de la table. A noter : un index multi-colonnes sur C2 + C3 ou C5 (voire les 2) pourrait être très intéressant, puisque tu te positionnerais en matchcols 2. La 2ème requête contient les mêmes prédicats, donc mêmes conclusions. Bonne utilisation. |
|
|
00
|
|
|
#3 |
|
Membre chevronné
![]() Administrateur de base de données Inscription : octobre 2006 Messages : 503 ![]() |
Bonjour
en complément de pdz74: si la création d'index est impossible ==> requete 1: réécrire la requete pour faire du scan sur T1 et de l'accès direct sur T2. Pour utiliser de facon minimale un index, il faut au moins utiliser la 1ere colonne de cet index. Il es normal que la requete 2 fasse du scan. a+ |
|
|
00
|
|
|
#4 |
|
Invité de passage
![]() Développeur COBOL Inscription : août 2011 Messages : 3 ![]() |
Bonjour et merci pour vos réponses.
Quelques infos supplémentaires importantes si je comprends bien vos indications. T1 et T2 contiennent disons 50000 occurences. C2 pas du tout discriminant (2 occurences max, 1 seule pour le moment) C3 et C5 sont discriminants mais sont des paramètres facultatifs de la requete. |
|
|
00
|
|
|
#5 |
|
Membre actif
![]() Inscription : juin 2008 Messages : 146 ![]() |
Dans ce cas, tu oublies l'index sur C2 (1 ou 2 valeurs discriminantes, ça n'apporte rien). Si les paramètres C3 et C5 sont facultatifs, cela signifie qu'avec l'écriture de cette seule requête, il t'arrive de renseigner les host variables concernant ces colonnes avec un truc du style '%%'. Pas bon...
Si tu crées un index sur C3 et un index sur C5, il y a de fortes chances que DB2 décide de faire du multiple index accès, et une intersection des Rid avant d'accéder aux datas. Ca marchera super bien avec des host variables renseignées. Mais avec des host variables non renseignées, cela te renverra sur la totalité des lignes de la table. Résultat, tu scannes 2 index et la table ! Si tu ne peux pas faire de sql dynamique, le mieux serait d'écrire 4 requêtes que tu exécuterais en fonction de ce que l'utilisateur a renseigné : - Si C3 et C5 renseignées, tu exécutes la requête actuelle. - Si C3 renseignée mais pas C5, tu exécutes une requête équivalente sans le prédicat sur C5. - Si C5 renseignée mais pas C3, tu exécutes une requête équivalente sans le prédicat sur C3. - Si C3 et C5 non renseignées, tu exécutes une requête équivalente sans les 2 prédicats sur C3 et C5. De cette manière, les chemins d'accès seront au mieux par rapport à la demande de l'utilisateur. Il y aura 1 cas avec scan de tables, mais ça, tu n'y peux rien puisque l'utilisateur n'a renseigné aucun critère de recherche. A noter : tu peux matcher tout cela avec la colonne C4 qu'il ne faut pas totalement oublier. Un prédicat >, c'est rarement génial, mais en fonction de ce qui est renseigné d'habitude dans cette colonne et du caractère discriminant de cette colonne, un index peut être à étudier. Ne pas oublier le principe suivant : si tes requêtes et tes index répondent à 99% des besoins, ça ne vaut peut-être pas le coup de trop investir sur le 1% restant, surtout pour des tables de 50.000 lignes, cad pas énormes. Reste la possibilité de demander à DB2 de recalculer les chemins d'accès au moment de l'exécution avec l'option de bind REOPT. DB2 est sensé faire au mieux en fonction de la valeur des host variables, mais j'avoue n'avoir jamais testé cette option qui revient à faire du sql dynamique, chose totalement prohibée dans nos environnements de prods. |
|
|
10
|
|
|
#6 |
|
Invité de passage
![]() Développeur COBOL Inscription : août 2011 Messages : 3 ![]() |
Je ne peux effectivement pas faire de SQL dynamique.
Je comprends bien l'intérêt d'écrire plusieurs requêtes en fonction des paramètres renseignés. Dans ce cas qu'en est il des index ? 1 index par requête ? Autre indication, C4 est une date et dans une utilisation normale ce critère sera bien discriminant. |
|
|
00
|
|
|
#7 |
|
Membre actif
![]() Inscription : juin 2008 Messages : 146 ![]() |
Si OK pour plusieurs requêtes, cela permet de créer un index sur C3 et un sur C5. Ces index seront pris en compte dans les 3 premières requêtes (unitairement ou ensemble). Quant à la dernière requête, ça reste en scan.
Pour C4, comme précisé dans mon message précédent, pourquoi pas, mais gaffe, tu as un >. Si tu as 50.000 dates et que tu recherches avec C4 > '2000-01-01', tu risques de ramener toutes les lignes et pourtant tu passeras inutilement par l'index. Autre possibilité, mettre C4 en 2ème colonne des index C3 et C5. De cette manière, DB2 appliquerait les 2 prédicats dès la lecture de l'index. Tu restes en matchcols 1 puisque tu as un LIKE pour la 1ère colonne, mais ça reste intéressant. |
|
|
20
|
Copyright © 2000-2012 - www.developpez.com