|
Publicité ' | ||||||||||||||||||||||||
|
|
#1 |
|
Nouveau Membre du Club
![]() Thibaut Inscription : février 2008 Messages : 115 ![]() |
Bonjour à tous,
Je vais essayer d'être assez précis pour que vous puissiez m'aider. J'ai actuellement une table qui contient des numéros de séries ( 436239 lignes). Le numéro de série est unique sur 18 caractères. J'ai donc mis un index unique dessus. Habitué à normaliser mes bases, j'utilise une clé primaire numérique. J'ai 3 tables qui font référence à la clé primaire numérique (dont 1 contenant 373914 lignes) Sur beaucoup de mes requêtes qui dépendent du numéro de série, j'ai des temps de réponse lent, pouvant attendre 11 secondes, ce qui n'est pas acceptable vu la faible quantité de données (Qu'est qu'un demi-million pour Oracle? Pour info, le client veut impérativement faire ses recherches en mode "contient" et non en mode "commence par". La plupart de mes requêtes ont donc un like "%<NUM_SERIE_LETTER>%'. J'ai testé différent réglage et essayer sur un base local pour voir si j'avais moyen d'optimiser tout ca. En dupliquant mon champ numéro de série sur les 2 tables référentes, ce qui m'évite une jointure sur la table NumSerie, j'obtiens des temps de réponses de 2 à 3 secondes (en mettant un index), ce qui pourrait paraitre acceptable. Mais alors dans ce cas, vu que le numéro de série est dupliqué dans 2 de mes tables référentes, ne serait-il pas mieux d'utiliser mon VARCHAR2(18) de numéro de série comme clé primaire plutôt qu'un numérique? Qu'en pensez-vous? |
|
00
|
|
|
#2 | ||
|
Expert Confirmé Sénior
![]() ![]() Marius NituIngénieur développement logiciels Inscription : octobre 2007 Messages : 3 311 ![]() |
Like "%<NUM_SERIE_LETTER>%' fait sauter n'importe quel index.
Code :
|
||
|
|
10
|
|
|
#3 | ||
|
Membre chevronné
![]() O. JolySupport Inscription : décembre 2010 Messages : 287 ![]() |
Comme le précise mnitu, le fait de rechercer en mode "contient" force un parcours complet de la table les statistiques oracle étant insuffisantes pour associer une sélectivité à un contenu.
Si vous êtes absolument certain qu'un passage par index sera plus rapide, vous pouvez indiquer à l'optimiseur d'utliser un parcours par index au moyen d'un "hint" au niveau de la requête. Code sql :
Mais avant toutes choses :
Bref, si le besoin est effectivement une requête en mode "contient" et que chaque requête doit au final remonter un grand nombre de lignes, de mauvaises performances sont à prévoir sans qu'on puisse y faire grand chose. |
||
|
10
|
|
|
#4 | ||
|
Nouveau Membre du Club
![]() Thibaut Inscription : février 2008 Messages : 115 ![]() |
Justement, je pensais aussi qu'Oracle (10g au passage) ne pouvait pas utiliser d'index avec like '%<FILTRE>%', mais mon EXPLAIN est formel. Il utilise l'index créé par l'unique key.
Code :
L'information remontée par la requête est 5 niveaux plus haut (5 jointures, ça fait beaucoup, je sais). Un critère like 'SN%' est relativement lent (11 secondes). Le EXPLAIN m'indique un coût de 36. C'est assez normal, mon critère ne filtre finalement pas grand chose, et il retourner 80% de la table. Mais ce qui est étrange, c'est que pour la même requête, le critère LIKE '%SN%' est plus rapide (2 secondes) alors que le coût du EXPLAIN est de 800. Les donnés stockées font que les 2 requêtes retournent les mêmes résultats. Les 2 requêtes m'indiquent utiliser l'index unique NUMSERIE_UK1. C'est étrange non? J'arrive pas à comprendre comment LIKE '%SN%' peut être plus performant. En revanche, Le like '<LETTRE_FILTER>%' devient plus performant à partir de 6 lettres saisies. Pour la justification du besoin client. Le numéro de série est constitué de lettres et chiffres qui peuvent correspondre parfois à des dates ou des modèles. C'est pourquoi l'utilisateur peut saisir directement '1001' pour avoir les numéros de séries de Janvier 2010, mais ce n'est pas la majorité des utilisateurs. Au début persuadé d'un gain de performance en mode "commence par", j'avais testé une modif de l'interface pour laisser le choix à l'utilisateur entre les 2 modes, libre à l'utilisateur de passer en mode "contient" et d'avoir des requêtes plus longues. Ce qui aurait satisfait la fonctionnalité et/ou la performance. Mais les performances ne sont pas si visible comme expliqué ci-dessus. |
||
|
00
|
|
|
#5 | ||||
|
Nouveau Membre du Club
![]() Thibaut Inscription : février 2008 Messages : 115 ![]() |
mnitu, j'obtiens bien le même explain que toi sur ma table avec un select simple sans jointure.
Code :
Code :
Dans tous les cas, vu que numéro de série est unique sur 18 caractères, me conseiller vu de l'utiliser comme primary key au détriment de mon id numérique? Ca me fait bizarre d'utiliser un varchar en clé primaire, mais c'est surement parce que je suis habitué à MySQL |
||||
|
00
|
|
|
#6 |
|
Expert Confirmé Sénior
![]() ![]() Marius NituIngénieur développement logiciels Inscription : octobre 2007 Messages : 3 311 ![]() |
La requête de type LIKE 'BS1001%' peut utiliser un index parce que vous avez le début de la chaîne des caractères et vous pouvez la comparer d'une manière efficace avec le contenu de l'index, exemple: BA10000, BA10010, ... BS10000, BS10010, BS100100, BS1001000, ... BT1000, ...
Mais comment voulez vous comparer efficacement le contenu de l'index ci dessus avec la condition LIKE '%10%' ? Parfois la seule utilisation de l'index dans ces conditions pourrait être de l'utiliser comme une table en full scan, donc de faire un index full scan. Mais cette possibilité est assez restrictive: la colonne doit être not null, le résultat doit pouvoir être obtenu que sur l'index. L’idée d’utiliser un hint me semble complètement erronée dans ce cas : en présence des bonnes statistiques l’optimiseur fait assez bien son boulot. Cinq table en jointure c'est rien, le base des données sont là pour faire des jointures. Mais pour avancer il faut déjà les requêtes ainsi que des autres informations. |
|
|
00
|
|
|
#7 | ||||||||
|
Nouveau Membre du Club
![]() Thibaut Inscription : février 2008 Messages : 115 ![]() |
Je comprend bien pourquoi un index fonctionne bien avec un like 'BS%'. Cela est dû à la structure B-Tree qui classe les valeurs dans un arbre, et il parcours l'index du noeud parent vers les sous-noeuds.
Toutefois, j'ai compris quelques choses entre temps, Oracle utilise également cet index pour les requête like '%BS%' car ma colonne est unique. Si je désactive la contrainte, il fait un full scan, et ca va plus vite! A ce propos, lorsqu'on crée un contrainte unique, Oracle crée un index implicite, mais est-ce exactement le même type d'index que si on crée un index unique? Code :
Code :
Du même type que : Code :
Les données de ma base correspondent à un Dump de la production. Les statistiques n'étant pas bonne au départ, j'avais fait sur les tables: Code :
Merci pour la réponse. |
||||||||
|
00
|
|
|
#8 | |||||||||||||
|
Expert Confirmé Sénior
![]() ![]() Marius NituIngénieur développement logiciels Inscription : octobre 2007 Messages : 3 311 ![]() |
Citation:
Citation:
Citation:
Citation:
Citation:
|
|||||||||||||
|
|
00
|
|
|
#9 | |||
|
Membre expérimenté
![]() François Inscription : février 2010 Messages : 305 ![]() |
Citation:
Concernant ce point, si j'ai compris, pour le SN% il utilise l'index. Et avec le message de mnitu #6, il apparait que pour %SN% il n'utilise pas l'index. Maintenant, si c'est bien ca ( ) je vous conseillerai les histogrammes.http://asktom.oracle.com/pls/asktom/...D:707586567563 Dans le cas ou vous recupererez 80% de la table, c'est plus rapide de faire un full table scan que d'utiliser un index. Maintenant, si le CBO ne sait pas qu'il y a beaucoup beaucoup de SN%, il y a peu de chance qu'il le devine. http://books.google.ch/books?id=TGSd...page&q&f=false Page suivante, la 179. Ca ne resout rien, mais ca peut expliquer un peu. |
|||
|
|
00
|
|
|
#10 | ||
|
Nouveau Membre du Club
![]() Thibaut Inscription : février 2008 Messages : 115 ![]() |
J'ai dû effectivement me mélanger les pinceaux, je n'arrive plus à voir dans un explain que oracle utilise l'index pour les like '%BS%'.
Pour la différence entre la contrainte unique et l'index, je sais bien qu'il n'y a pas de différence dans un explain, je me posais juste la question de savoir pourquoi les 2 syntaxes était possible? Je n'ai pas les privilèges suffisant pour DBMS_STATS, j'ai fais une demande pour avoir le privilège, on verra bien. Voici la requête : Code :
La version est la Oracle Database 10g. |
||
|
00
|
|
|
#11 |
|
Membre confirmé
![]() Grégoire MARTINIngénieur développement logiciels Inscription : janvier 2011 Messages : 128 ![]() |
Bonjour,
Peut on avoir les plans ? |
|
|
00
|
|
|
#12 |
|
Nouveau Membre du Club
![]() Thibaut Inscription : février 2008 Messages : 115 ![]() |
Les plans d'éxecution sont dans les 2 fichiers txt joint précédemment
|
|
00
|
|
|
#13 |
|
Expert Confirmé Sénior
![]() ![]() Marius NituIngénieur développement logiciels Inscription : octobre 2007 Messages : 3 311 ![]() |
Pour l’instant laissé à coté les contraintes et autres modifications de la requête.
Commencez par calculer les statistiques sur toutes les tables et indexes de la requête. Dans l’analyse de la requête on constate que vous sélectionnez que depuis la table Produit, et encore un peu en trop parce que vous utilisez distinct. Par contre tous vos critères sont ailleurs sur les autres tables. Le temps de réponse de ce type de requête dépende beaucoup de la capacité de filtrage dans les premières étapes du plan d’exécution. Quand vous ajoutez la contrainte d’unicité il y a création d’un index unique. Cet index n’a pas des statistiques à jour par défaut. Il est nécessaire toujours dans ces conditions de calculer les statistiques pour l’index en question sinon les informations transmises à l’optimiseur sont incomplètes ce qui peut conduire à un mauvais plan. |
|
|
00
|
|
|
#14 | |||
![]() Inscription : décembre 2002 Messages : 2 385 ![]() |
Citation:
Code :
__________________
Consultant / formateur Oracle indépendant Certifié OCP 10g et 11g, sécurité 11g |
|||
|
|
10
|
|
|
#15 |
|
Membre chevronné
![]() O. JolySupport Inscription : décembre 2010 Messages : 287 ![]() |
Si la table et l'index ont étés créés avant l'insertion des données il serait bon de recalculer les stats sur les 2 objets.
D'autre part, il semblerait que le calcul simultané de statistiques par dbms_stats et analyze détraquerait l'optimiseur. Il faudrait donc se contenter d'utiliser une méthode (de préfrence dbms_stats). |
|
00
|
|
|
#16 |
|
Nouveau Membre du Club
![]() Thibaut Inscription : février 2008 Messages : 115 ![]() |
L'insertion des données a été faite à la création de l'index. On m'a confirmé qu'un refresh dbms_stats avait lieu toutes les nuits. Mes calculs étaient donc peut-être faussé. Je vais donc attendre pour en savoir plus. Je vous tiens au courant.
|
|
00
|
|
|
#17 | |
![]() ![]() |
Citation:
Si un index existe déjà à la création de la contrainte, Oracle ne va pas en créer un nouveau. De plus, dans le cas d'une contrainte d'unicité déferrable, l'index créé ne sera pas unique non plus. Un index est un objet physique qui est là pour épauler la base de données, une contrainte est un élément fonctionnellement restrictif. La contrainte d'unicité s'appuie toujours d'un index, mais ce dernier n'est pas forcément unique.
__________________
Email : http://scr.im/waldar |
|
|
00
|
|
|
#18 | |||||||||
|
Nouveau Membre du Club
![]() Thibaut Inscription : février 2008 Messages : 115 ![]() |
Que d'heure perdu pour des mauvaises statistiques
J'ai mis un schéma (ultra light) pour que ce soit plus claire. developpez.png A partir de GroupeTestNumSerie, il existe 2 liens vers produit (Direct et par groupeTest), mais c'est normal. L'un est le lien administratif, et l'autre réel. Constatant dans tout les cas de meilleurs performances, j'ai préféré dé-normaliser un peu mes données pour éviter une jointure sur 2 tables importante. J'ai donc mis le numéro de série dans GroupeTestNumSerie avec un index non unique (possibilité de doublon dans cette table). Voici la nouvelle requête: Code :
Code :
En revanche, je re-testé l'ancienne requête en allant jusqu'à la table numSerie. Les temps de réponse sont toujours très lent Code :
Code :
Citation:
|
|||||||||
|
00
|
|
|
#19 |
|
Expert Confirmé Sénior
![]() ![]() Marius NituIngénieur développement logiciels Inscription : octobre 2007 Messages : 3 311 ![]() |
|
|
|
00
|
|
|
#20 | |
|
Expert Confirmé Sénior
![]() ![]() Marius NituIngénieur développement logiciels Inscription : octobre 2007 Messages : 3 311 ![]() |
Citation:
Mais, néanmoins ma remarque est incorrecte pour le cas général. |
|
|
|
00
|
Copyright © 2000-2012 - www.developpez.com