J'ai lu composite indexes
et je suis un peu confus au sujet de la commande. Cette documentation (un peu moins de la moitié) indique
En général, vous devez d'abord placer la colonne devant être utilisée le plus souvent dans l'index.
Cependant, peu de temps après
créer un index composite mettant la colonne la plus sélective en premier; c'est-à-dire la colonne avec le plus de valeurs.
Oracle le dit aussi ici en d'autres termes
Si toutes les clés sont utilisées de la même manière dans les clauses WHERE, le classement de ces clés de la plus sélective à la moins sélective dans l'instruction CREATE INDEX améliore au mieux les performances de la requête.
Cependant, j'ai trouvé une réponse SO qui dit différemment. Ça dit
Disposez les colonnes avec la colonne la moins sélective en premier et la colonne la plus sélective en dernier. Dans le cas d'un lien avec la colonne qui est plus susceptible d'être utilisé seul.
La première documentation que j'ai référencée dit que vous devez d'abord passer par le plus souvent utilisé alors que la réponse SO dit que cela ne devrait être que pour le bris d'égalité. Ensuite, ils diffèrent également sur la commande.
Cette documentation parle également skip scanning
et dit
Le saut de balayage est avantageux s'il y a peu de valeurs distinctes dans la colonne de tête de l'index composite et de nombreuses valeurs distinctes dans la clé non-leader de l'index.
Un autre article dit
La colonne de préfixe doit être la plus discriminante et la plus utilisée dans les requêtes
qui, selon moi, est le plus discriminant et le plus distinctif.
Toutes ces recherches m'amènent toujours à la même question; La colonne la plus sélective doit-elle être la première ou la dernière? La première colonne doit-elle être la plus utilisée et la plus sélective lors d'un bris d'égalité?
Ces articles semblent se contredire, mais ils offrent quelques exemples. D'après ce que j'ai rassemblé, il semble plus efficace least selective column
d'être le premier dans la commande si vous prévoyez Index Skip Scans
. Mais je ne suis pas vraiment sûr que ce soit correct.
la source
Réponses:
De AskTom
L'un des arguments pour organiser les colonnes dans l'index composite dans l'ordre des moins discriminantes (valeurs moins distinctes) aux plus discriminantes (valeurs plus distinctes) est la compression des clés d'index.
Selon les statistiques de l'indice, le premier indice est plus compressible.
Un autre est la façon dont l'index est utilisé dans vos requêtes. Si vos requêtes utilisent principalement
col1
,Par exemple, si vous avez des requêtes comme-
select * from t where col1 = :a and col2 = :b;
select * from t where col1 = :a;
-Alors,
index(col1,col2)
cela fonctionnerait mieux.Si vos requêtes utilisent principalement
col2
,select * from t where col1 = :a and col2 = :b;
select * from t where col2 = :b;
-Alors,
index(col2,col1)
cela fonctionnerait mieux. Si toutes vos requêtes spécifient toujours les deux colonnes, peu importe la colonne qui arrive en premier dans l'index composite.En conclusion, les considérations clés dans l'ordre des colonnes de l'index composite sont la compression des clés d'index et la façon dont vous allez utiliser cet index dans vos requêtes.
Les références:
la source
La plus sélective en premier n'est utile que lorsque cette colonne se trouve dans la clause WHERE réelle.
Lorsque le SELECT est par un groupe plus grand (moins sélectif), puis éventuellement par d'autres valeurs non indexées, un index avec des colonnes moins sélectives peut toujours être utile (s'il y a une raison de ne pas en créer un autre).
S'il y a une ADRESSE de table, avec
COUNTRY CITY STREET, autre chose ...
l'indexation de STREET, CITY, COUNTRY produira les requêtes les plus rapides avec un nom de rue. Mais en interrogeant toutes les rues d'une ville, l'index sera inutile et la requête effectuera probablement une analyse complète de la table.
L'indexation COUNTRY, CITY, STREET peut être un peu plus lente pour les rues individuelles, mais l'index peut être utilisé pour d'autres requêtes, en sélectionnant uniquement par pays et / ou ville.
la source
Lors du choix de l'ordre des colonnes d'index, la préoccupation principale est:
Y a-t-il des prédicats (égalité) contre cette colonne dans mes requêtes?
Si une colonne n'apparaît jamais dans une clause where, cela ne vaut pas l'indexation (1)
OK, vous avez donc un tableau et des requêtes pour chaque colonne. Parfois plus d'un.
Comment décidez-vous quoi indexer?
Regardons un exemple. Voici un tableau à trois colonnes. L'une contient 10 valeurs, 1000 autres, les 10 000 dernières:
Ce sont des chiffres remplis de zéros. Cela aidera à faire le point sur la compression plus tard.
Vous avez donc trois requêtes courantes:
Qu'indexez-vous?
Un index sur seulement few_vals n'est que légèrement meilleur qu'un scan de table complet:
Il ne vaut donc probablement pas la peine d'être indexé seul. Les requêtes sur lots_vals renvoient quelques lignes (seulement 1 dans ce cas). Donc, cela vaut vraiment la peine d'être indexé.
Mais qu'en est-il des requêtes sur les deux colonnes?
Devriez-vous indexer:
OU
Question piège!
La réponse n'est ni l'un ni l'autre.
Bien sûr, few_vals est une longue chaîne. Vous pouvez donc en tirer une bonne compression. Et vous (pourriez) obtenir une analyse de saut d'index pour les requêtes en utilisant (few_vals, lots_vals) qui n'ont que des prédicats sur lots_vals. Mais je ne le fais pas ici, même s'il fonctionne nettement mieux qu'une analyse complète:
Aimez-vous le jeu? (2)
Vous avez donc toujours besoin d'un index avec lots_vals comme colonne de tête. Et au moins dans ce cas, l'indice composé (peu, beaucoup) fait la même quantité de travail qu'un seul sur (lots)
Il y aura des cas où l'indice composé vous fera économiser 1 à 2 E / S. Mais vaut-il la peine d'avoir deux index pour cette économie?
Et il y a un autre problème avec l'index composite. Comparez le facteur de regroupement pour les trois index, y compris LOTS_VALS:
Notez que le facteur de clustering pour few_lots est 10 fois plus élevé que pour lots et lots_few! Et ceci est dans une table de démonstration avec un clustering parfait pour commencer. Dans les bases de données du monde réel, l'effet est probablement pire.
Alors qu'est-ce qui est si mauvais à ce sujet?
Le facteur de regroupement est l'un des principaux facteurs déterminant le caractère «attrayant» d'un indice. Plus il est élevé, moins l'optimiseur est susceptible de le choisir. Surtout si les lots_vals ne sont pas réellement uniques, mais ont normalement quelques lignes par valeur. Si vous n'avez pas de chance, cela pourrait suffire à faire croire à l'optimiseur qu'une analyse complète est moins chère ...
OK, donc les index composites avec few_vals et lots_vals n'ont que des avantages de cas de bord.
Qu'en est-il des requêtes filtrant plusieurs-valeurs et plusieurs-valeurs?
Les index à colonnes uniques n'offrent que de petits avantages. Mais combinés, ils renvoient peu de valeurs. Un indice composite est donc une bonne idée. Mais dans quel sens?
Si vous en placez quelques-uns en premier, la compression de la colonne de tête la réduira
Avec moins de valeurs différentes dans la première colonne, la compression est meilleure. Il y a donc un peu moins de travail pour lire cet index. Mais seulement légèrement. Et les deux sont déjà un bon morceau plus petit que l'original (diminution de 25% de la taille).
Et vous pouvez aller plus loin et compresser tout l'index!
Maintenant, les deux index sont de retour à la même taille. Notez que cela profite du fait qu'il existe une relation entre peu et beaucoup. Encore une fois, il est peu probable que vous constatiez ce genre d'avantages dans le monde réel.
Jusqu'à présent, nous n'avons parlé que des contrôles d'égalité. Souvent, avec des index composites, vous aurez une inégalité par rapport à l'une des colonnes. par exemple des requêtes telles que "obtenir les commandes / expéditions / factures pour un client au cours des N derniers jours".
Si vous avez ces types de requêtes, vous voulez l'égalité par rapport à la première colonne de l'index:
Notez qu'ils utilisent l'index opposé.
TL; DR
1: Dans certains cas, il peut être utile d'inclure une colonne dans un index si cela signifie que toutes les colonnes de votre requête se trouvent dans l'index. Cela permet une analyse d'index uniquement, vous n'avez donc pas besoin d'accéder à la table.
2: Si vous avez une licence pour les diagnostics et l'optimisation, vous pouvez forcer le plan à un saut d'analyse avec SQL Plan Management
ADDEDNDA
PS - les documents que vous avez cités proviennent de 9i. C'est vraiment vieux. Je m'en tiendrai à quelque chose de plus récent
la source
select count (distinct few_vals || ':' || many_vals || ':' || lots_vals )
vraiment courante? Oracle n'autorise-t-il pas la syntaxeselect count (distinct few_vals, many_vals, lots_vals )
- qui ne fait aucune concaténation de chaîne, n'a pas besoin que les colonnes soient des types de texte et ne repose pas sur l'absence de:
caractère?count ( distinct x, y, z )
dans Oracle. Vous devez donc effectuer une sous-requête distincte et compter les résultats ou une concaténation comme ci-dessus. Je viens de le faire ici pour forcer un accès à la table (plutôt que pour un scan d'index uniquement) et n'avoir qu'une ligne dans le résultatIl y a plus d'éléments de requête qui contribuent à la décision finale sur ce qu'un index composite doit commencer et / ou contenir en plus de la sélectivité de la colonne.
par exemple:
">,> =, <, <="
pour garder la conversation pertinente, ma réponse ci-dessous s'applique à la situation suivante:
chaîne"
D'après mon expérience, c'est à la fois que DBA devrait être attentif.
1) Si je crée un index avec la colonne la plus sélective en premier mais que cette colonne n'est pas réellement utilisée par la plupart des requêtes sur cette table, cela ne sert à rien pour le moteur db.
2) Si je crée un index avec la colonne la plus utilisée dans une requête en premier dans l'index mais que la colonne a une faible sélectivité, les performances de ma requête ne seront pas bonnes.
Je vais lister les colonnes qui sont principalement utilisées dans 90% des requêtes de table. Ensuite, mettez ceux-ci uniquement dans l'ordre de la plus grande cardinalité à la moindre cardinalité.
Nous utilisons des index pour améliorer les performances de la requête de lecture et ce flux de travail (types de requête de lecture) doit uniquement conduire la création de l'index. En fait, au fur et à mesure que les données augmentent (des milliards de lignes), l'index compressé peut économiser du stockage, mais nuire à la performance des requêtes de lecture.
la source
En théorie, la colonne la plus sélective donne la recherche la plus rapide. Mais au travail, je suis juste tombé sur une situation où nous avons un indice composite de 3 parties avec la partie la plus sélective en premier. (date, auteur, maison d'édition, disons, dans cet ordre, le tableau surveille les pouces vers le haut sur les messages) et j'ai une requête qui utilise les 3 parties. Mysql utilise par défaut l'index onlny de l'auteur en sautant l'index composite contenant la société et la date bien qu'ils soient présents dans ma requête. J'ai utilisé force index pour utiliser le composite et la requête s'est en fait déroulée plus lentement. Pourquoi est-ce arrivé? Je vais vous dire:
Je sélectionnais une plage à la date, donc malgré une date très sélective, le fait que nous l'utilisions pour des analyses de plage (même si la plage est relativement courte, 6 mois sur 6 ans de données) a rendu le composite nocif pour mysql. Pour utiliser le composite dans ce cas particulier, mysql doit récupérer tous les articles écrits depuis les nouvelles années, puis plonger dans qui est l'auteur, et étant donné que l'auteur n'a pas écrit autant d'articles par rapport à d'autres auteurs, mysql a préféré simplement trouver cet auteur .
Dans un autre cas, la requête a été exécutée beaucoup plus rapidement sur le composite, dans le cas où un auteur était extrêmement populaire et possédait la plupart des enregistrements, le tri par date étant logique. Mais mysql n'a pas détecté automatiquement ce cas, j'ai dû forcer l'index ... Donc vous savez, ça varie. Les analyses de plage peuvent rendre votre colonne sélective inutile. La distribution des données pourrait rendre les cas où les colonnes sont plus sélectives pour différents enregistrements ...
Ce que je ferais différemment, c'est de déplacer la date (qui encore une fois, en théorie, est la plus sélective) vers la droite, car je sais que je vais effectuer un balayage de plage maintenant et cela fait une différence.
la source
WHERE (date BETWEEN @x AND @y) AND (author = @a) AND (publishing company = @p)
alors un index on(author, publishing_company, date)
ou on(publishing_company, author, date)
serait mieux et serait utilisé - sans le forcer.Différents cas pour différentes situations. Connaissez votre objectif; puis créez vos index et exécutez des plans pour chacun et vous aurez votre meilleure réponse à votre situation.
la source
De l' ordre des colonnes dans l'index sur Ask Tom:
D'accord, que nous devons ordonner les colonnes en fonction de la clause where, mais la déclaration "(la sélectivité de a ou b ne compte pas du tout)" n'est pas correcte.) ". Les colonnes les plus sélectives doivent être en tête si elles sont satisfaites premier rôle ("clause where")
la source