Pourquoi oracle tableau indexé, mais encore ne full table scan?
J'ai une table 'MSATTRIBUTE' avec 3000K lignes. J'ai utilisé la requête suivante pour récupérer les données, cette requête a différents plan d'exécution avec la même DB de données, mais dans différentes env. dans un env, il ressort de l'analyse complète de sorte que la requête est très lent, mais dans un autre env tout utilisé d'analyse d'index, c'est très bon, tout le monde qui sait pourquoi il ont plein balayage de table dans un env parce que j'ai construit l'index pour eux, comment puis-je laisser devenir index scan, tout comme ce que j'ai testé dans env 1. comment je peux améliorer cette requête?
N'est-ce pas
Merci. oui, exactement.
A l'index a été ajouté récemment (c'est pas clair pour moi), et si oui, avez-vous recueilli des statistiques depuis? Vous pouvez vérifier la
L'index est-il présent dans tous les milieux? Êtes-vous d'utiliser la même version du logiciel, dans tous les milieux? Quels sont vos environnements?
l'indice a été construit lors de la création de la table, de sorte qu'il n'a pas été ajouté récemment. les données est la même, j'utilise imp/exp importer à partir d'une base de données(env) et de l'exporter vers un autre env, la seule différence est l'une env, oracle 11g R1 qui a utilisé full table scan, une autre base de données qui a utilisé l'indice de scan est 11g R2, mais je pense que cette petite version de la différence ne serait pas affecter l'exécution du plan.
3000K == 3M
? 😉Merci. oui, exactement.
A l'index a été ajouté récemment (c'est pas clair pour moi), et si oui, avez-vous recueilli des statistiques depuis? Vous pouvez vérifier la
last_analyzed
colonne de all_tables
et all_indexes
; pour un nouvel indice, ce dernier peut être null. L'optimiseur peut ne pas envisager d'utiliser l'index si c'est le cas.L'index est-il présent dans tous les milieux? Êtes-vous d'utiliser la même version du logiciel, dans tous les milieux? Quels sont vos environnements?
l'indice a été construit lors de la création de la table, de sorte qu'il n'a pas été ajouté récemment. les données est la même, j'utilise imp/exp importer à partir d'une base de données(env) et de l'exporter vers un autre env, la seule différence est l'une env, oracle 11g R1 qui a utilisé full table scan, une autre base de données qui a utilisé l'indice de scan est 11g R2, mais je pense que cette petite version de la différence ne serait pas affecter l'exécution du plan.
OriginalL'auteur C.c | 2013-01-23
Vous devez vous connecter pour publier un commentaire.
sans comprendre de façon plus que je me soucie de savoir à propos de votre modèle de données et vous les affaires c'est dur de donner des conseils utiles. Mais voici quelques remarques à propos de votre stratégie d'indexation et pourquoi je pense que l'optimiseur n'est pas à l'aide de la indxes vous avez.
Dans la sous-requête le chemin d'accès à REDLINE_MSATTRIBUTE les lecteurs à partir de trois colonnes:
CLASSE n'est pas indexé. mais ce n'est sans doute pas très sélectif. OBJECT_ID
est le leader de la colonne d'un composé de l'indice, mais les autres colonnes ne sont pas pertinentes de la sous-requête.
Mais le plus gros problème est CHANGE_RELEASE_DATE. Ce n'est pas indexée à tous. Ce qui est une mauvaise nouvelle, comme un clé primaire look donne une date qui est alors comparé avec CHANGE_RELEASE_DATE. Si une colonne n'est pas indexé teh de la base de données a lire le tableau d'obtenir ses valeurs.
De la requête principale s'éloigne
ATTID est indexé, mais comment sleective est que l'index? L'optimiseur probablement ne pense pas que c'est très sélectif. ATTID est également un index composé avec CHANGE_ID et OLD_VALUE mais aucun d'entre eux sont les premières colonnes, ce qui n'est pas très utile. Et nous avons discuté de la CLASSE, CHANGE_RELEASE_DATE et OBJECT_ID déjà.
L'optimiseur ne choisissez d'utiliser un index si c'est moins cher (moins de lectures) qu'une analyse de table. Cela signifie généralement la clause where critères à la carte à la leader (c'est à dire le plus à gauche) les colonnes d'un index. Cela pourrait être le cas avec OBJECT_ID et ATTID dans la sous-requête, sauf que
Donc, vous pourriez obtenir une certaine amélioration par la création d'un index sur
(CHANGE_RELEASE_DATE, CLASS, OBJECT_ID, ATTID)
. Mais comme je l'ai dit dès le départ, sans en savoir plus sur votre situation, ces sont tout simplement mal informés des suppositions.OriginalL'auteur APC
Si les lignes sont dans un ordre différent dans les deux tables, les index dans les deux systèmes peuvent avoir différents facteurs de clustering, et donc de la différence des coûts estimés pour l'indice d'accès. Vérifier la table et l'index de la statistique, y compris le facteur groupement, pour voir si il y a des différences significatives.
Également, procédez de l'une des systèmes d'expliquer les plans de mentionner échantillonnage dynamique?
Comme vous pouvez le voir la clause where de 4 conditions, les deux colonnes sont indexés, mais deux: CHANGE_RELEASE_DATE(type date) et la classe(nombre) ne sont pas indexés, cela cause un env utilise full table scan?
exp/imp ne permet pas de conserver la ligne de commande.
Vérifiez l'onglet "statistiques", pas des "états". Si le clustering coefficient est différent alors les lignes peuvent être différemment commandé, mais il dépend aussi de la façon dont de nombreux blocs les deux versions de la table.
Merci, je vais vérifier l'index "statistiques" pour voir est-il différent
OriginalL'auteur David Aldridge
lorsque oracle a un index et décide d'utiliser/ne pas utiliser c'est peut-être parce que
1) vous pouvez avoir des paramètres différents pour OPTIMIZER_MODE - assurez-vous qu'il n'est pas sur RBO.
2) les données sont différentes - dans ce cas, oracle pourrait évaluer la requête stats différemment.
3) les données sont les mêmes, mais les stats ne sont pas à jour. dans ce cas - recueillir des statistiques
4) il y a beaucoup plus de raisons pourquoi oracle ne sera pas utiliser l'index dans un environnement, je vous suggère la comparaison de paramètres (tels que la OPTIMIZER_ INDEX_COST_ADJ etc...)
OriginalL'auteur haki
Une question immédiate est de cette pièce, SÉLECTIONNEZ RELEASE_DATE DE CHANGEMENT where ID = 136972355 (Ce morceau de code sera exécuté pour chaque ligne de retour et il n'a pas besoin de... une meilleure manière de faire ceci est d'utiliser un cartésienne de la table, de sorte qu'il ne s'exécute une fois et retourne une valeur statique pour comparer....
Exemple 1:
Est toujours plus rapide qu'
Select * from Table1 Où Date > Sysdate -- Sysdate sera appelée pour chaque ligne comme c'est une fonction dynamique en fonction de la valeur. L'exemple précédent peut résoudre une fois pour une littérale et considérablement plus rapide. et je crois que c'est définitivement une fois que la pièce de blesser votre requête et forcer une analyse de la table.
Je crois aussi que c'est un moyen plus efficace pour exécuter la requête.
+1 pour @Florian, comme ces ensembles de résultats peuvent être mis en cache, même quand ils sont corrélés.
que la requête s'exécute, il doit vérifier l'état actuel de la date de sortie qui pourrait avoir changé au cours de votre requête... selon votre niveau d'isolement de ce qui pourrait cache ou cache pas... le cardinal méthode garantit l'exécution de fois pour obtenir une valeur statique et se résout à une littérale et est toujours plus rapide.... si vous testez Où date > sysdate sur un million de lignes de la table une méthode cartésienne sera de 10 à 30% plus rapide...
si vous avez le niveau d'isolement commis lu il y aura des extra-dessus de la tête pour s'assurer que le moteur db vérifie en permanence la date de sortie pour voir si il a une nouvelle valeur d'engagement.... donc plus de frais généraux ... le produit cartésien de la méthode de l'évaluation des garanties d'une valeur statique une fois ... c'est aussi un truc discuté sur asktom...
Il n'y a pas besoin d'Oracle pour re-vérifier si les valeurs ont changé. La façon dont Oracle poignées de déclaration de niveau de cohérence avec les ANNULER, toutes les parties de la requête sont la garantie de toujours renvoyer des données de la même point dans le temps. Oracle n'a pas non validées lire, si vous êtes toujours payer que les frais généraux. sous-Requête de mise en cache devrait empêcher que la sous-requête d'exécution pour chaque ligne, même si je ne suis pas sûr de quelle version il a été introduit.
OriginalL'auteur