2009-01-31 6 views
0

Je ne sais pas beaucoup sur l'optimisation des bases de données, mais je suis en train de comprendre ce cas.Indice unique sur deux colonnes plus un index séparé sur chacune d'elles?

Dire que j'ai le tableau suivant:

cities 
=========== 
state_id integer 
name varchar(32) 
slug varchar(32) 

Maintenant, dis que je veux effectuer des requêtes comme ceci:

SELECT * FROM cities WHERE state_id = 123 AND slug = 'some_city' 
SELECT * FROM cities WHERE state_id = 123 

Si je veux le « limaces » pour une ville d'être unique au sein de son état particulier, j'ajouterais un index unique sur state_id et slug.

Est-ce suffisant indice? Ou devrais-je aussi ajouter un autre sur state_id afin que la deuxième requête soit optimisée? Ou la deuxième requête utilise-t-elle automatiquement l'index unique?

Je travaille sur PostgreSQL, mais je sens que ce cas est si simple que la plupart des SGBD fonctionnent de la même.

Aussi, je sais que cela ne fait pas sûrement une différence sur les petites tables, mais mon exemple est simple. Pensez aux tables de 200k + lignes.

Merci!

+0

Il semble que ce sujet est plus complexe que je ne le pensais. Merci à tous pour votre participation. – Ivan

Répondre

1

Un seul index unique sur (id_état, slug) devrait suffire. Pour être sûr, bien sûr, vous aurez besoin d'exécuter EXPLAIN et/ou ANALYZE (peut-être avec l'aide de quelque chose comme http://explain.depesz.com/), mais finalement quels index sont appropriés dépend très étroitement du type de requêtes que vous exécuterez. Rappelez-vous que les index accélèrent les SELECT et les INSERTs, UPDATEs et DELETEs plus lentement, de sorte que vous ne voulez idéalement que le nombre d'index nécessaires.

De plus, PostgreSQL dispose d'un optimiseur de requêtes intelligent: il utilisera des plans de recherche radicalement différents pour les requêtes sur les petites tables et les tables volumineuses. Si la table est petite, elle effectuera une analyse séquentielle et ne prendra même pas en charge les index, étant donné que la surcharge de travail avec eux est plus importante que le simple filtrage brutal de la table. Cela change à un plan différent une fois que la taille de la table dépasse un seuil, et peut changer à nouveau si la table devient plus grande, ou si vous modifiez votre SELECT, ou ....

Résumé: vous ne pouvez pas faire confiance aux résultats EXPLAIN et ANALYZE sur des ensembles de données beaucoup plus petits ou différents de vos données réelles. Faites-le fonctionner, puis faites-le vite plus tard (si vous en avez besoin).

0

Pour ne pas utiliser d'optimisation EXPLIQUEZ http://www.postgresql.org/docs/7.4/static/sql-explain.html et voir pour votre auto. Mais l'optimisation n'est pas la raison la plus importante pour faire ces index; c'est d'abord une contrainte qui empêche une base de données de ne pas être logique.

1

[EDIT: Misread la question ... Si tout va bien, ma réponse est plus pertinente maintenant]

Dans votre cas, je vous suggère 1 index sur (state_id, slug). Si jamais vous avez besoin de rechercher juste par slug, ajoutez un index sur seulement cette colonne. Si vous avez ceux-ci, puis en ajoutant un autre indice sur state_id est inutile que le premier indice couvre déjà.

Un index peut être utilisé lorsqu'un segment initial de ses colonnes est utilisé dans une clause WHERE. Ainsi, par exemple un index sur les colonnes A, B et C optimisera les requêtes contenant les clauses WHERE impliquant A, B et C, les clauses WHERE avec juste A et B, ou les clauses WHERE avec juste A. Notez que l'ordre dans lequel les colonnes apparaissent dans la définition d'index est très important - cet exemple d'index ne peut pas être utilisé pour les clauses WHERE impliquant seulement B et/ou C.

(Bien sûr, c'est à l'optimiseur de requêtes de savoir si un index particulier est effectivement utilisé, mais dans votre cas avec 200k lignes ., vous pouvez garantir qu'une simple recherche par state_id ou slug ou les deux utilisera l'un des indices)

1

Tout optimiseur décent verra un index sur trois colonnes - dire:

CREATE INDEX idx_1 ON SomeTable(Col1, Col2, Col3); 

et utilisera cet indice pour l'une des conditions suivantes:

WHERE Col1 = ...something... 

WHERE Col1 = ...something... AND Col2 = ...otherthing... 

WHERE Col3 = ....whatnot.... 
    AND Col1 = ...something.... 
    AND Col2 = ...otherthing... 

C'est, il utilisera l'index s'il y a des conditions appliquées à un sous-ensemble de premier plan contigu des colonnes de l'index. Bien que j'aie utilisé l'égalité, elle peut aussi s'appliquer aux intervalles (ouvert - juste supérieur à, par exemple) ou fermé (entre deux valeurs).

Questions connexes