web-dev-qa-db-fra.com

Comment décider quand utiliser index sur une colonne de table

Quand devrais-je utiliser index sur table?

  1. À partir de combien de lignes index est logique?
  2. Si j'ai un tableau avec des lignes constantes, les colonnes juste éditées viennent d'être éditées (pas dans la clause 'Where'), cela a du sens d'index même si le tableau a à peu près 15 lignes? EDIT: Dans ce cas, la sélection/lecture non indexée peut-elle être plus efficace que la lecture indexée?

EDIT: Maintenant, je travaille avec Firebird 2.5, mais la plupart du temps j'utilise SQL Server 2005/2008. 

14
Fanda

En général, ma stratégie d’indexation serait la suivante (j’utilise SQL Server exclusivement pour le moment - adaptez-le à votre propre système de base de données si nécessaire):

  • choisissez une clé de regroupement bon - ni un GUID, ni une VARCHAR(250) ou quelque chose - une clé de regroupement bon est étroite, unique, stable, toujours croissante - comme un INT IDENTITY est parfait. En fait votre clé primaire en cluster -> vous donne votre premier index sur la table

  • pour toute colonne utilisée comme clé étrangère dans une autre table, ajoutez un index. Il peut s'agir soit d'un index de colonne unique, soit d'un index composé, selon ce qui convient le mieux à votre cas. Il est important que la colonne de clé étrangère soit la colonne first de cet index (si vous utilisez un index composé) - sinon, les avantages pour les JOIN ou pour la vérification de l'intégrité référentielle ne seront pas disponibles pour votre système.

Et c'est tout pour l'instant.

Ensuite: lancez votre système - observez et mesurez - établissez une base de référence. L'application est-elle assez rapide? Si oui -> vous avez terminé - rentrez chez vous et profitez de votre temps libre.

Sinon, commencez à collecter des données et des indications sur les raisons pour lesquelles l'application n'est pas assez rapide. Regardez par exemple des éléments tels que les DMV de SQL Server qui vous renseignent sur les requêtes les moins performantes, ou le index manquant DMV . Analysez-les. Voyez ce que vous pourriez améliorer. Ajoutez un index à la fois et encore: observez, mesurez, comparez à votre niveau de référence.

Si vous avez une amélioration -> laissez cet index en place et cette mesure est votre nouvelle base de référence. Rincez et répétez jusqu'à ce que vous (et vos utilisateurs) soyez satisfaits des performances de l'application (et then / rentrez chez vous et profitez de votre temps libre).

La sur-indexation dans SQL Server peut être pire que de ne pas avoir d’index. Ne commencez pas avec trop d'indices pour commencer! Établissez uniquement bon clé en cluster et index non en cluster de clé étrangère - c'est tout - puis observez, mesurez, optimisez et répétez ce cycle.

27
marc_s

C’est une discussion très complexe, il ya plusieurs choses à garder à l’esprit. En règle générale, vous ne devriez pas considérer un index en fonction du nombre de lignes que vous avez sur votre table, mais en fonction des requêtes que vous exécutez. Un index aidera uniquement à sélectionner les requêtes et, dans le même temps, réduira légèrement les performances des insertions, des suppressions et des mises à jour, car outre la modification de la ligne de la table, vous devez également modifier l'index.

Vous semblez être nouveau en la matière, je vous suggère donc d'examiner vos plans d'exécution et d'essayer d'éliminer toutes les opérations «d'analyse», car elles lisent à peu près toutes les tables, voire tous les index. Vous devriez toujours chercher à avoir des recherches, mais vous devez équilibrer le nombre d'index que vous avez sur votre table.

Si vous utilisez SQL Server, vous pouvez exécuter une trace avec le profileur SQL Server pour vous aider.

MODIFIER:

Dans ce cas, la sélection/lecture non indexée peut-elle être plus efficace que la lecture indexée ?

oui, mais si cela se produit, le moteur sera suffisamment intelligent pour ne pas utiliser l'index

5
Diego

Un index est utile pour sélectionner une fraction des lignes d'une table. Interroger une valeur de clé primaire est la meilleure utilisation d'un index. Le pire scénario est d'accéder à toutes les lignes d'une table via un index, car il doit lire les pages d'index et / pages de données référencées. Un autre exemple est qu'un tri en mémoire d'un jeu de résultats peut être plus rapide que le tri d'un jeu de résultats via un index sur la colonne triée. Et n'oubliez jamais qu'un index peut améliorer les performances des requêtes, mais un index diminue les performances en écriture.

Certains ont suggéré de prendre une référence, d'utiliser un type d'utilitaire de traçage pour mesurer les performances, etc. Si les performances établies vous conviennent, passez à autre chose. Sinon, analysez le plan d'exécution, le modèle de données physique (index disponibles), recalculez les statistiques et voyez si cela aide l'optimiseur à choisir un meilleur plan d'exécution. Assurez-vous que le SGBD peut (est autorisé) à utiliser la RAM disponible. Essayez de minimiser les E/S du disque, etc.

Dans le cas de Firebird 2.5, la nouvelle API Firebird Trace est une aubaine. Vous pouvez enfin obtenir une trace en temps quasi réel sur ce qui est exécuté dans la base de données avec des compteurs de performance (plan d'exécution, durée d'exécution, statistiques d'E/S, etc.). Et un produit tiers appelé FB TraceManager de Upscene Productions fait de l’API Trace un plaisir à utiliser.

1
tsteinmaurer

J'utilise cette requête pour obtenir un indice sur les tables qui ont besoin d'un index:

-- Missing Indexes for current database by Index Advantage  (Query 57) (Missing Indexes)
SELECT DISTINCT CONVERT(decimal(18,2), user_seeks * avg_total_user_cost * (avg_user_impact * 0.01)) AS [index_advantage], 
migs.last_user_seek, mid.[statement] AS [Database.Schema.Table],
mid.equality_columns, mid.inequality_columns, mid.included_columns,
migs.unique_compiles, migs.user_seeks, migs.avg_total_user_cost, migs.avg_user_impact,
OBJECT_NAME(mid.[object_id]) AS [Table Name], p.rows AS [Table Rows]
FROM sys.dm_db_missing_index_group_stats AS migs WITH (NOLOCK)
INNER JOIN sys.dm_db_missing_index_groups AS mig WITH (NOLOCK)
ON migs.group_handle = mig.index_group_handle
INNER JOIN sys.dm_db_missing_index_details AS mid WITH (NOLOCK)
ON mig.index_handle = mid.index_handle
INNER JOIN sys.partitions AS p WITH (NOLOCK)
ON p.[object_id] = mid.[object_id]
WHERE mid.database_id = DB_ID() 
ORDER BY index_advantage DESC OPTION (RECOMPILE);

Notez que cela ne vous donnera qu'un nord, vous devez toujours prendre en compte ce qui a été répondu ci-dessus.

0
Luis Teijon

En ce qui concerne la deuxième partie de votre question, si une table ne comporte que 15 lignes, il est très probable que, quel que soit le nombre d’index dont vous disposez, la table sera toujours analysée, car elle est si petite.

0
Tim Harkin