Question

Supposons que j'ai une table de base de données avec deux champs, "foo". et "bar". Aucune d'entre elles n'est unique, mais chacune d'entre elles est indexée. Cependant, plutôt que d'être indexés ensemble, ils ont chacun un index séparé.

Supposons maintenant que j'exécute une requête telle que SELECT * FROM quelque chose WHERE = foo = 'hello' AND bar = 'world'; Ma table comporte un très grand nombre de lignes pour lesquelles foo est 'hello' et un petit nombre de lignes pour lesquelles la barre est "monde".

La tâche la plus efficace pour le serveur de base de données est donc d'utiliser l'index de barres pour rechercher tous les champs où bar est "monde", puis de ne renvoyer que les lignes pour lesquelles foo est "bonjour". C’est O (n) où n est le nombre de lignes où bar est 'world'.

Cependant, j’imagine qu’il est possible que le processus se déroule à l’inverse, où l’indice fo a été utilisé et les résultats recherchés. Ce serait O (m) où m est le nombre de lignes où foo est 'hello'.

Oracle est-il assez intelligent pour effectuer une recherche efficace ici? Qu'en est-il des autres bases de données? Ou est-ce que je peux le dire dans ma requête pour effectuer une recherche dans le bon ordre? Peut-être en mettant bar = 'world' en premier dans la clause WHERE ?

Était-ce utile?

La solution

Oracle utilisera certainement l’index le plus sélectif pour piloter la requête. Vous pouvez le vérifier à l’aide du plan explique.

De plus, Oracle peut combiner l’utilisation des deux index de différentes manières: il peut convertir des index btree en bitmaps et effectuer une opération bitmap ANd sur eux, ou effectuer une jointure par hachage sur les ID de ligne renvoyés par les deux index.

Un facteur important à prendre en compte ici pourrait être toute corrélation entre les valeurs interrogées. Si foo = 'hello' représente 80% des valeurs de la table et bar = 'world', 10%, Oracle va estimer que la requête renverra 0,8 * 0,1 = 8% des lignes de la table. Cependant, cela peut ne pas être correct - la requête peut en réalité renvoyer 10% des rwos ou même 0% des lignes, selon la corrélation entre les valeurs. Maintenant, en fonction de la distribution de ces lignes dans la table, il peut ne pas être efficace d'utiliser un index pour les trouver. Vous devrez peut-être encore accéder (par exemple) à 70% ou aux blocs de la table pour récupérer les lignes requises (google pour "facteur de clustering"), auquel cas Oracle effectuera une analyse complète de la table si l'estimation est correcte.

En 11g, vous pouvez collecter des statistiques multicolonnes pour vous aider dans cette situation, je crois. En 9i et 10g, vous pouvez utiliser l'échantillonnage dynamique pour obtenir une très bonne estimation du nombre de lignes à récupérer.

Pour obtenir le plan d'exécution, procédez comme suit:

explain plan for
SELECT *
FROM   sometable
WHERE  foo='hello' AND bar='world'
/
select * from table(dbms_xplan.display)
/

Comparez cela avec:

explain plan for
SELECT /*+ dynamic_sampling(4) */
       *
FROM   sometable
WHERE  foo='hello' AND bar='world'
/
select * from table(dbms_xplan.display)
/

Autres conseils

Oui, vous pouvez donner des "astuces". avec la requête à Oracle. Ces astuces sont déguisées en commentaires ("/ * HINT * /") à la base de données et sont principalement spécifiques au fournisseur. Donc, un indice pour une base de données ne fonctionnera pas sur une autre base de données.

Je voudrais utiliser les indices ici, le premier indice pour le petit tableau. Voir ici .

Par contre, si vous effectuez souvent des recherches sur ces deux champs, pourquoi ne pas créer un index sur ces deux champs? Je n'ai pas la bonne syntaxe, mais ce serait quelque chose comme

CREATE INDEX IX_BAR_AND_FOO on sometable(bar,foo);

De cette façon, la récupération des données devrait être assez rapide. Et si la concaténation est unique, vous créez simplement un index unique qui devrait être extrêmement rapide.

Eli,

Dans un commentaire que vous avez écrit:

  

Malheureusement, j'ai une table avec beaucoup de colonnes, chacune avec son propre index. Les utilisateurs peuvent interroger n'importe quelle combinaison de champs. Par conséquent, je ne peux pas créer efficacement d'index sur chaque combinaison de champs. Mais si je n'avais que deux champs nécessitant des index, je serais tout à fait d'accord avec votre suggestion d'utiliser deux index. & # 8211; Eli Courtwright (29 septembre à 15h51)

Il s’agit en réalité d’une information cruciale. Parfois, les programmeurs se surpassent en posant des questions. Ils essaient de résumer la question jusqu’aux points essentiels, mais souvent trop de simplifier et d’obtenir la meilleure réponse.

Ce scénario explique précisément pourquoi les index bitmap ont été inventés - pour gérer les moments où des groupes de colonnes inconnus seraient utilisés dans une clause where.

Juste au cas où quelqu'un dirait que les IMC concernent uniquement les colonnes à faible cardinalité et pourraient ne pas s'appliquer à votre cas. Low n'est probablement pas aussi petit que vous le pensez. Le seul problème réel est la simultanéité de DML et de la table. Doit être simple ou rare pour que cela fonctionne.

  

Oracle est-il assez intelligent pour effectuer une recherche?   efficacement ici?

La réponse simple est "probablement". Il y a beaucoup de gens très brillants chez chacun des fournisseurs de bases de données qui travaillent à l'optimisation de l'optimiseur de requêtes. Il s'agit donc probablement de faire des choses auxquelles vous n'aviez même pas pensé. Et si vous mettez à jour les statistiques, vous en ferez probablement plus.

Tout d’abord, je suppose que vous parlez de bons index normaux, normaux et b * -tree. La réponse pour les index bitmap est radicalement différente. Et il existe de nombreuses options pour divers types d’index dans Oracle qui peuvent ou non modifier la réponse.

Au minimum, si l'optimiseur est capable de déterminer la sélectivité d'une condition particulière, il utilisera l'indice plus sélectif (c'est-à-dire l'indice sur barre). Mais si vous avez des données asymétriques (il y a N valeurs dans la barre de colonnes mais la sélectivité d’une valeur donnée est sensiblement supérieure ou inférieure à 1 / N des données), il vous faudrait un histogramme sur la colonne pour indiquer l'optimiseur dont les valeurs sont plus ou moins probables. Et si vous utilisez des variables de liens (comme le souhaitent tous les bons développeurs OLTP), en fonction de la version Oracle, des problèmes peuvent survenir avec le furtif des variables de liens.

Potentiellement, Oracle pourrait même effectuer une conversion à la volée des deux index b * -tree en images bitmap et les combiner afin de pouvoir utiliser les deux index pour rechercher les lignes à récupérer. Mais il s’agit d’un plan de requête assez inhabituel, en particulier s’il n’ya que deux colonnes pour lesquelles une colonne est très sélective.

Je suis certain que Oracle peut également afficher un plan de requête afin de savoir exactement quel index est utilisé en premier.

Vous pouvez indiquer quel index utiliser. Je ne connais pas bien Oracle, mais vous pouvez utiliser Mysql avec USE | IGNORE | FORCE_INDEX (voir ici pour plus de détails). Pour obtenir de meilleures performances, utilisez un index combiné.

La meilleure approche serait d’ajouter foo à l’index de barre, ou d’ajouter bar à l’index de foo (ou les deux). Si l'index de foo contient également un index sur la barre, ce niveau d'indexation supplémentaire n'affectera pas l'utilité de l'index de foo dans les utilisations actuelles de cet index, ni de manière sensible les performances du maintien de cet index, mais cela donnera à la base de données des informations supplémentaires. informations à utiliser pour optimiser les requêtes, comme dans l'exemple.

C'est mieux que ça.

Les recherches d'index sont toujours plus rapides que les analyses de table complètes. En coulisse, Oracle (et le serveur SQL d'ailleurs) localisera d'abord la plage de lignes des deux index. Il examinera ensuite la plage la plus courte (en s’agissant d’une jointure interne), puis itérera la plage la plus courte pour rechercher les correspondances avec la plus grande des deux.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top