4

J'ai une table dans l'environnement de production qui a 2 index sur une table avec les mêmes colonnes dans l'index mais dans l'ordre inverse.Oracle 2 Index sur les mêmes colonnes mais ordre différent

DDL est

- CREATE INDEX IND_1 ON ORDERS (STORE_ID,DIST_ID) 
- CREATE INDEX IND_DL_1 ON ORDERS (DIST_ID,STORE_ID) 

-ce que ces deux indices ne pas essentiellement les mêmes. Pourquoi quelqu'un créerait-il de tels index? Est-ce que l'inversion ou le changement de position de colonne fait quelque chose en interne?

+0

La règle de base pour l'ordre des colonnes dans un index est que vous voulez ** réduire la taille de l'arborescence secondaire ** (ce qui signifie, le deuxième niveau et sur)! donc vous voulez mettre la valeur avec la valeur la plus distincte en premier. – haki

+0

Ces index ressemblent à des candidats parfaits pour [compression d'index] (http://docs.oracle.com/cd/E11882_01/server.112/e26088/statements_5012.htm#BABHDBHE). –

+1

@haki Ce n'est pas comme ça que fonctionnent les B-Trees. Vous ne réduirez pas le nombre de nœuds si vous placez d'abord une colonne plus sélective dans l'index composite. Il n'y a pas de "niveau B-Tree pour la première colonne" en haut, "niveau pour la deuxième colonne" en dessous etc ... En fait, mettre une colonne moins sélective en premier peut aider avec la compression d'index Oracle et peut physiquement ordonner l'index façon (en fonction de la façon dont vous voulez interroger). Pour citer Tom Kyte: _ "Cela n'a pas été vrai puisque au moins la version 6 ayant le plus sélectif en premier est meilleure." _ –

Répondre

4

Les index sont liés aux champs qu'ils indexent, dans l'ordre dans lequel ils sont définis dans l'index. Tant que vous utilisez les champs de l'index, dans leur ordre gauche-> droit, l'index est utilisable pour votre requête. Si vous ignorez des champs, l'index ne peut pas être utilisé. par exemple. compte tenu de l'indice suivant:

CREATE INDEX ind1 ON foo (bar, baz, qux) 

alors ceux-ci où les clauses seront en mesure d'utiliser l'index:

WHERE bar=1 
WHERE bar=1 AND baz=2 
WHERE baz=2 AND bar=1 <--same as before 
WHERE bar=1 AND baz=2 AND qux=3 

L'ordre dans lequel vous utilisez les champs indexés dans la requête est pas pertinente, juste que vous utilisez leur. Cependant, l'ordre dans lequel ils sont définis dans l'index est critique. Les clauses suivantes ne peuvent pas utiliser l'index:

WHERE baz=2 <-- 'bar' not being used 
WHERE baz=2 AND qux=3 <-- 'bar' again not being used 
WHERE bar=1 AND qux=3 <-- the index can be partially used to find `bar`, but not qux. 

Pour vos deux cas, il n'y a rien vraiment mal avec la façon dont ils sont indexés, mais ce serait un peu plus efficace à l'index comme suit:

(STORE_ID, DIST_ID) 
(DIST_ID) 

Il ne sert à rien d'indexer store_id dans le second index, car le SGBD peut utiliser le premier index pour gérer les recherches store_id. Ce n'est pas un gain majeur, mais quand même ... le maintien des index est une surcharge pour la DB, et la réduction des frais généraux est toujours une bonne chose.

+2

+1 - Vous ignorez les scans d'index, cependant. Votre deuxième ensemble de clauses pourrait utiliser l'index. Mais il devrait s'agir d'un balayage par saut moins efficace (en particulier lorsque le nombre de valeurs distinctes dans la colonne principale augmente) plutôt que d'un balayage de portée plus efficace. –

+2

En outre, la dernière déclaration n'est pas tout à fait correcte.L'index '((store_id, dist_id)' ne serait pas le plus efficace pour une requête comme 'dist_id = xxx et store_id <10'. D'un autre côté, ceci est trouvé pour 'dist_id, store_id'. –

+1

* "Réduire les frais généraux est toujours une bonne chose" * - sauf si les frais généraux supplémentaires * enregistrés ici * entraînent des performances médiocres *. –

1

Oracle ne doit pas toucher les segments de table dans les cas où toutes les informations nécessaires sont trouvées dans les index. Dans votre cas, ces index peuvent servir de table de recherche/traduction rapide STORE_ID => DIST_ID et vice-versa.

Il suffit de regarder le plan exec pour la requête où vous sélectionnez ne sélectionnez que STORE_ID basé sur DIST_ID, la requête ne passera par index, et ne touchera pas la table elle-même.

Mais peut-être que la raison est différente (le cas échéant).

Questions connexes