2009-09-09 6 views
6

ATM J'essaie d'apprendre à utiliser efficacement les inidices de base de données et j'apprécierais de recevoir des commentaires d'experts. Je n'ai aucun problème de performance actuellement. Je voudrais juste savoir, comment vous gérer vos indices avec cette requête:Comment accélérer cette requête?

SELECT B.event, 
     COALESCE(B.system, C.surname || ' ' || C.forename) AS name, 
     C.label, 
     B.timestamp 
FROM A    
    INNER JOIN B ON A.event=B.event 
    INNER JOIN C ON B.state=C.id 
    LEFT OUTER JOIN D ON B.hur=D.id    
WHERE A.id IN(12,13,14,15,...) 
    ORDER BY B.event, B.timestamp 

A.id, C.id et D.id sont déjà les clés primaires

MISE À JOUR Normalement, je mettrais INDEX (A.event) et INDEX (B.event, B.timestamp). Est-ce correct? Et qu'en est-il de B.event, B.state et B.hur?

+0

Correct, mais vérifiez si B.timestamp serait effectivement utilisé. – Pomyk

+0

Quelle est la taille de chacune des tables et combien de lignes correspondrait-il à une requête donnée? Quelle base de données utilisez-vous? –

+0

De même, à quelle fréquence les données sont-elles ajoutées aux tables et à quelle fréquence souhaitez-vous exécuter la requête? –

Répondre

3

Ressaisissez votre requête comme ceci:

SELECT B.event, 
     COALESCE(B.system, C.surname || ' ' || C.forename) AS name, 
     C.label, 
     B.timestamp 
FROM B    
INNER JOIN 
     C 
ON  C.id = B.state 
LEFT OUTER JOIN 
     D 
ON  D.id = B.hur 
WHERE B.event IN 
     (
     SELECT event 
     FROM A 
     WHERE A.id IN (12, 13, 14, 15) 
     ) 
ORDER BY 
     B.event, B.timestamp 

, et créer un index composite sur B (event, timestamp)

2

Vous pouvez ajouter des index à tout dans les clauses WHERE et ORDER BY. C'est à dire A.event, B.event et B.timestamp.

+1

N'ajoutez pas d'index à l'aveugle. Voir la réponse de Lieven. L'ajout aveugle d'index peut nuire aux performances car chaque index doit être conservé. Dans certains cas, comme dans le cas de petites tables, cela nuira à la façon dont les opérations d'information conservées pourraient être utilisées ailleurs. Parfois, une analyse de table complète sur une petite table est meilleure que les index. – jim

+0

Je suis tenté de supprimer ma réponse; Cependant, le commentaire de Jim est une information utile, alors la réponse devrait-elle être laissée? – darasd

0
SELECT B.event, B.system, COALESCE(C.surname) || ' ' || COALESCE(C.forename) AS name, C.label, B.timestamp 
FROM A    
INNER JOIN B ON A.event=B.event 
INNER JOIN C ON B.state=C.id 
LEFT OUTER JOIN D ON B.hur=D.id    
WHERE A.event = ANY(:visits) 
ORDER BY B.event, B.timestamp 

L'ORDER BY ralentira également les choses. Assurez-vous que ceux-ci sont indexées:

A.event 
B.event 
B.state 
C.id 
B.timestamp 
3

Je prends habituellement ces étapes en essayant d'accélérer mes requêtes

  1. analyser le plan d'exécution. Essayez de créer des index (couvrant) pour éliminer les balayages de table.
  2. essayez de créer (en couvrant) des index pour éliminer les balayages d'index.

Quant à vous interroger, vous ne seriez pas vous tromper avec la création d'index sur

  • A.event
  • B.event
  • B.state
  • B.Hur
+0

La création d'index distincts pour B.event et B.state n'est pas la même chose que la création d'un index sur (B.event, B.state). Il est important de différencier cela car cela a un impact direct sur les performances. – MatBailie

+0

@Dems: si cela n'était pas clair dans ma réponse, vous avez raison. –

1

Je voudrais ajouter des index à tout ce qui est joint, dans la clause where ou dans la clause order by.

Dans ce cas, ajoutez les index des éléments suivants (en supposant les champs d'identification sont les clés primaires et déjà indexés):

  1. A.event
  2. B.event
  3. B.state
  4. B. Hur
  5. B.event, B.timestamp (indice combiné des deux champs)

Le 5ème, étant une combinaison d'index devrait accélérer la commande par. Vous devez modérer le nombre d'index, par rapport à toute baisse de performance dans l'insertion d'enregistrements dans la table (plus vous ajoutez d'index à la table, plus les insertions et mises à jour sont lentes, car les index doivent être mis à jour) .

2

Il est important de noter que l'ordre des champs de l'index est important.

Un index est, dans un sens, un arbre de recherche. Si vous indexez (B.event, B.state), l'arborescence regroupe tous les enregistrements avec le champ save "event", puis les ordonne par le champ "state".

Si vous deviez ensuite interroger cet index pour "b.state = x", l'index serait peu utile; L'index est trié par "l'événement" en premier.


Dans votre exemple:
- Filtre A par sa "événement"
- rejoindre A.event à B.event
- rejoindre B.state à C.id
- Inscrivez-vous B.hur = D.id
- ordre par B.event, B.timestamp

Il est important de noter que le optimize se penchera sur les statistiques de vos tables et index, peuvent ensuite réarranger l'ordre de les jointures. Le résultat sera le même, mais l'ordre peut donner des performances différentes, et le travail des optimiseurs consiste à essayer de trouver la meilleure performance.

Dans votre cas, je m'attendrais à ce que l'ordre de B.event soit extrêmement important. Simplement parce que c'est l'ordre de la sortie qui en résulte, ET c'est le champ que vous filtrez.

Ensuite, vous rejoignez B.state à C.id. Avoir et indexer sur C.id est donc bon, cela rend la jointure plus rapide. Mais également, avoir les données de la table B dans un bon ordre peut aussi rendre la jointure plus rapide. Mais, ayant un index sur B.event et un index séparé sur B.state peut donner peu. L'index B.state devient presque inutile car nous utilisons l'index B.event. Si vous combinez les deux dans un index (b.event puis b.state) le plan d'exécution peut trouver un moyen d'utiliser la partie b.state de l'index.

Enfin, si vous mettez tous les champs dans l'index, l'index s'agrandit, mais la requête n'aura peut-être jamais besoin de regarder la table. L'information est dans l'index. Le temps nécessaire pour aller d'un index à la table pour trouver les champs 'manquants' est similaire à celui d'une jointure. Donc, pour les performances de lecture, l'ajout de champs supplémentaires à l'index peut être significatif.

Je Wittering maintenant, mais le résumé est ceci:
- En général, index séparé sur les champs séparés ne sont pas utilisés ensemble
- Pour les index composites, l'ordre dans lequel vous spécifiez les champs fait une différence
- L'ajout de champs 'supplémentaires' à l'index le rend plus grand, mais peut également accélérer les requêtes
- L'ordre du plan d'exécution est plus important que l'ordre de votre requête
- Mais les index dont vous disposez peuvent déterminer l'ordre de le plan d'exécution

Ce type de travail a pas de réponses catégoriques. Il dépend tellement de vos données qu'il est plus proche d'un art.

Une option consiste à surcharger les tables avec des index, à examiner le plan d'exécution résultant et à supprimer les index inutiles.

Mais même là, une mise en garde s'applique. Comme le plan d'exécution dépend des données (et des statistiques de table), il est très important d'avoir des données réelles dans les tables. Alors que les tables ont 10 'ou 100s de lignes, un plan d'exécution peut être le plus rapide. Mais lorsque vous obtenez des millions de lignes, le plan d'exécution peut changer et bénéficier ainsi de différents index.

2

Exécutez l'analyse de la requête, et lisez-la - si cela ne vous aide pas - mettez la sortie d'analyse expliquée sur explain.depesz.com et vérifiez ce qu'elle "dit".

Questions connexes