Est-ce une optimisation prématurée d'ajouter des index de base de données?

61

Un de mes collègues aujourd’hui a suggéré que nous examinions toutes les requêtes de notre application et que nous ajoutions des index en conséquence.

Je pense que cette optimisation est prématurée car notre application n'est même pas encore publiée. J'ai suggéré de surveiller les requêtes lentes une fois que nous sommes en ligne, puis d'ajouter des index en conséquence.

Quel est le consensus général lors de la conception de votre base de données, devez-vous ajouter un index correspondant chaque fois que vous écrivez une nouvelle requête? Ou vaut-il mieux surveiller et voir comment ça se passe?

Marco de Jongh
la source
32
Cela pourrait être une question d’opinion, mais j’estime que certains index pourraient être ajoutés a priori.
Basile Starynkevitch le
2
@BasileStarynkevitch Totalement d'accord sur le fait que nous avons déjà des index de clés primaires et les travaux. Mais où tracez-vous la ligne?
Marco de Jongh
1
Mes deux sous d'expérience: je testais certaines de mes premières requêtes de recherche sur un sous-ensemble de notre base de données. Les tests que j'ai effectués étaient totalement satisfaisants sur ma copie locale. J'ai ensuite poussé l'application vers la zone de transfert qui héberge la base de données complète. Mes tests ont duré moins de 500 ms , alors que la résolution du système de test avait nécessité plusieurs minutes . Mon patron était confus quant aux raisons pour lesquelles l'application ne se chargeait pas. Les opérations de type Explain sont votre ami ... Recherchez au moins des analyses séquentielles sur de grandes tables, du moins!
Chris Cirefice
2
Ne pas ajouter d'index, c'est comme utiliser bubbleort. Le plus souvent, vous ne rencontrerez aucun problème lorsque vous le testerez, mais une fois que votre programme sera mis à l'échelle, vous rencontrerez de nombreux problèmes. Et les index peuvent facilement faire un facteur 100 en différence de vitesse.
Pieter B
3
Rappelez-vous toujours qu'un index n'est pas une chose magique qui accélérera vos requêtes. Un index entraînera des coûts sur la plupart des opérations DML et, en fonction du type, peut entraîner de nombreuses attentes lorsque de nombreuses personnes mettent à jour le même tableau. Pour les requêtes: Il existe de nombreuses requêtes qui ne bénéficient pas du tout d'un index, où un FTS est le plus rapide ou où le partitionnement fait tout le travail pour vous. - Ajoutez uniquement un index où vous savez qu'ils seront bénéfiques!
Falco

Réponses:

132

L'optimisation prématurée consiste à "optimiser" quelque chose en raison d'un sentiment vague et intuitif qui, vous le savez, sera probablement lent, en particulier au détriment de la lisibilité et de la maintenabilité du code . Cela ne signifie pas délibérément ne pas suivre les bonnes pratiques bien établies en matière de performance.

Parfois, c'est une ligne difficile à tracer, mais je dirais certainement que ne pas ajouter d'index avant de commencer, c'est une optimisation trop tardive . cela punira les utilisateurs précoces - vos utilisateurs les plus enthousiastes et les plus importants - et leur donnera une vision négative de votre produit, qu’ils répartiront ensuite dans des revues, des discussions, etc. bonne idée, mais je m'assurerais de le faire au plus tard à la version bêta.

Maçon Wheeler
la source
11
Oui, cela devrait être fait pendant la phase de test de charge
Alvaro le
152
Optimiser avant de savoir où se trouvent les pièces lentes est une optimisation prématurée. Libérer la chose avant de savoir où sont les parties lentes est une libération prématurée !
MathematicalOrchid
4
@ MathematicalOrchid: C'est un excellent phrasé! Puis-je l'emprunter ailleurs?
Pieter Geerkens
3
@PieterGeerkens Bien sûr, assommez-vous! ;-) Je suis juste triste que 91+ votes positifs ne me rapportent rien ... heh.
MathematicalOrchid
3
@ MathematicalOrchid aurait dû être une réponse. Pourrait courir pour "le plus petit droit-au-point" réponse jamais.
Mindwin
48

surveiller les requêtes lentes une fois que nous allons vivre

Parce que rien ne dit qualité comme faire souffrir vos utilisateurs pour un manque de design!

Vous devez savoir quelles requêtes ont besoin d’index lors de la conception des tables, ainsi que des colonnes interrogées dans les clauses where et les jointures. Celles-ci devraient déjà être indexées car ce qui pourrait ne pas être apparent dans un environnement réel peut devenir rapidement apparent lorsque la charge ou les données stockées augmentent. Ce que vous ne voulez pas faire quand cela se produit, c'est de claquer des index sur chaque requête "lente", vous obtiendrez un index sur tout.

gbjbaanb
la source
10
Droite. Considérons les index dans le cadre de la conception de la base de données. Utilisez des index pour éviter une analyse complète de la table pour toute requête que l'utilisateur final effectuera généralement en temps réel.
AE
1
@ DocBrown Je n'en suis pas si sûr, lorsque vous concevez une table, vous avez (ou devriez avoir) une certaine compréhension de la façon dont elle sera utilisée. Une table de personne sera interrogée par ID, ou éventuellement par nom de famille. Si quelqu'un commence à accéder via DoB, adresse ou numéro de téléphone, vous allez ajouter des index pour chaque champ - et où finit-il?!
gbjbaanb
4
@gbjbaanb: il se termine lorsque les utilisateurs cessent d'ajouter des fonctionnalités au produit, ce qui peut n'être "jamais" en fonction de votre méthodologie.
Steve Jessop
1
@SteveJessop Je veux dire que vous indexez en fonction des colonnes principales auxquelles vous souhaitez accéder. Pour une table de personnes, vous pouvez avoir une fonction de recherche (si vous oubliez votre nom d'utilisateur, vous pouvez par exemple effectuer une recherche par courrier électronique), mais vous utiliserez ensuite toujours l'ID. Donc, ID est le seul à nécessiter une indexation. Si vous effectuez beaucoup de recherches sur d'autres champs, vous voudrez peut-être un index, cela sortira avec le temps, mais en général, vous ne voulez pas indexer toutes les colonnes simplement parce que quelqu'un a parfois décidé d'écrire une requête non standard, mais vous pourriez utiliser un mécanisme différent pour ces cas "ponctuels".
gbjbaanb
2
@gbjbaanb: bien sûr, les gens ne devraient pas chercher à plusieurs reprises le même nom de famille dans une table, car il s'agit d'une poignée légèrement plus pratique à gérer que la clé appropriée pour la table. Je dirais que c'est le cas, que la table soit indexée sur le nom de famille ou non, en fait, puisqu'il y a quelque chose de très louche dans un bout de code qui suppose que tout fonctionne sur "le même utilisateur" mais qui n'arrive pas à exprimer cela dans le code en me souvenant de l'identifiant :-) J'imaginais des cas où le besoin de recherche inversée n'était pas anticipé jusqu'à ce que le client l'ait mentionné ...
Steve Jessop
26

"Optimisation prématurée", dans son sens péjoratif, signifie une optimisation coûteuse qui pourrait ne pas être nécessaire. Cela ne signifie pas que toutes les optimisations mises en œuvre avant le dernier point possible pour éviter la faillite!

En particulier, il est légitime d’optimiser à partir de tests de performance avant la mise en production, afin de vous assurer que vous pourrez répondre à certaines exigences sensibles (bien qu'approximatives) selon lesquelles votre application ne doit pas aspirer.

Au minimum, vous devez charger votre base de données avec une quantité plausible de données de test et vérifier la réactivité de votre application. Ce n'est pas prématuré, car vous savez que cela va arriver, et il va capturer toutes les requêtes qui déclenchent des analyses absurdement lentes. Comme AE le dit dans un commentaire:

Utilisez des index pour éviter une analyse complète de la table pour toute requête que l'utilisateur final effectuera habituellement en temps réel.

Du moins, pour les tables dont l'utilisation est prévue.

En guise de raccourci, si vous avez une expérience significative du moteur de base de données et que vous avez déjà planifié les tests lorsque vous écrivez la première copie du code, vous savez souvent, sans même l'exécuter, que la requête que vous êtes l'écriture sera trop lente sans index. Bien sûr, vous êtes libre de faire semblant de ne pas savoir et de regarder le test échouer avant d’ajouter l’index pour le faire passer, mais il n’ya aucune raison pour que du code défectueux (parce qu’il ne répond pas) soit mis en ligne.

Steve Jessop
la source
20

Je pense que cette optimisation est prématurée car notre application n'est même pas encore publiée. J'ai suggéré de surveiller les requêtes lentes une fois que nous sommes en ligne, puis d'ajouter des index en conséquence.

Vous ne pouvez pas traiter vos utilisateurs finaux et votre environnement de production comme une assurance qualité. En d'autres termes, vous dites que vous le découvrirez en production. Je ne pense pas que ce soit la bonne façon, et je vois que cette approche va terriblement mal tous les jours .

N'oubliez pas une chose, vous ne pouvez pas la peindre avec un pinceau large.

Quelle est votre charge de travail commune ?

Cela peut paraître évident ou ennuyeux, mais c’est important dans la pratique. Si vous avez 10 requêtes qui constituent 98% de votre charge de travail (assez commun, croyez-le ou non), ma recommandation serait une analyse sérieuse avant la production . Avec des données réalistes et représentatives, assurez-vous que ces 10 requêtes sont aussi performantes que possible ( parfait est une perte de temps précieux et presque impossible à réaliser).

Pour les 200 autres requêtes qui composent les 2% de la charge de travail , ce sont celles qui ne valent probablement pas la peine de faire beaucoup d'efforts et qui constitueront la solution idéale pour résoudre les problèmes de production. C'est aussi une réalité et pas une très mauvaise chose. Mais cela ne signifie pas ignorer les meilleures pratiques en matière d'indexation ou émettre des hypothèses sur la récupération des données.

Il est courant et utile de déterminer les performances de la base de données avant la production. En fait, il existe une position relativement commune pour ce type de choses, appelée DBA de développement .

Mais...

Certains vont trop loin et deviennent fous en ajoutant des index "au cas où". Quelqu'un recommande-t-il un index manquant? Ajoutez-le et quatre autres variations. Aussi une mauvaise idée. Vous devez non seulement penser à la récupération de vos données, mais également à la modification des données. Plus vous avez d'index sur une table, en général, plus vous avez de temps système lorsque vous modifiez des données.

Comme la plupart des choses, il existe un bon équilibre.

Comme une petite note amusante ... La pluralisation de "Index"

Les "indices" sont pour les financiers

Les "index" sont pour nous

Thomas Stringer
la source
2
Cela nécessite plus de votes. Je ne pourrais pas être plus d'accord.
RubberDuck
+1 pour le bit "juste au cas où" (ce serait une optimisation prématurée). Si je pouvais, je voterais à nouveau pour le bit "charge de travail commune".
David
J'espère que vous savez à l'avance quelles 10 requêtes appartiennent aux 98% et lesquelles ne le sont pas.
Paŭlo Ebermann
@ PaŭloEbermann La plupart des SGBD ont la capacité de capturer ces informations assez rapidement et facilement. Dans ce cas, il n'y a aucune excuse pour ne pas savoir.
Thomas Stringer le
@ThomasStringer Bien sûr, cela ne fonctionne que si vos scénarios de test avant de passer en production sont liés d'une manière ou d'une autre à ce que font de vrais utilisateurs en production.
Paŭlo Ebermann
4

Non, ce n'est pas une optimisation prématurée, mais il faut le faire correctement, comme devrait l'être toute optimisation.

Voici ce que je ferais:

  1. Chargez la base de données avec suffisamment de données de test pour imiter une charge de production. Vous ne pouvez pas obtenir cette précision à 100% mais c'est très bien: mettez juste assez de données. Une table a-t-elle une quantité fixe de données? Chargez-le. Avez-vous une table contenant beaucoup de données, par exemple une table contenant des questions sur ce site? Chargez quelques millions d'enregistrements même s'il ne s'agit que de données factices.
  2. Activer le profilage sur votre serveur de base de données.
  3. Décrochez l'application en utilisant une combinaison de scripts automatisés (fournit du volume) et d'utilisateurs réels (ils savent comment casser des choses).
  4. Passez en revue les données de profilage. Des requêtes spécifiques sont-elles lentes? Vérifiez les plans expliqués et voyez si le serveur de base de données vous dit qu'il veut un index mais qu'il n'existe pas.

Les serveurs de base de données sont des logiciels complexes et intelligents. Ils peuvent vous dire comment les optimiser si vous savez écouter.

Les clés doivent mesurer les performances avant et après l'optimisation et laisser la base de données vous dire ce dont elle a besoin .


la source
3

Suivre des modèles éprouvés pour des problèmes connus (comme trouver un enregistrement par son ID) n’est pas prématuré. C'est juste raisonnable.

Cela dit, les indices ne sont pas toujours une affaire simple. Pendant la phase de conception, il est souvent difficile de savoir à quels index votre trafic dépendra et quelles sont les opérations d'écriture goulot d'étranglement. Je préconiserais donc de tirer parti de certaines meilleures pratiques "évidentes" en matière de conception de schéma (utilisez des PK appropriées pour les modèles de lecture / écriture conçus et les FK d'index); mais, ne mettez pas d'index sur quoi que ce soit d'autre jusqu'à ce que vos tests de stress l'exigent.

svidgen
la source
Dépenser 30 secondes de plus pour effectuer une tâche dont l’amélioration des performances et la probabilité de nuire est presque certain, n’est pas une «optimisation prématurée». Si 90% des opérations d'une table utilisent une colonne particulière comme clé, alors l'indexation améliorera les performances, ou les performances ne seront jamais assez lentes, et l'ajout de code pour créer l'index peut prendre moins de temps que de déterminer si elle est vraiment nécessaire.
Supercat
@supercat "jamais" ... Jusqu'à ce que vous voyiez des blocages dans votre environnement de production ...
svidgen
Quelles sortes de scénarios réalistes envisagez-vous qui seraient compatibles avec 90% des opérations utilisant une colonne comme clé et dans lesquelles l'ajout d'un index entraînerait une impasse?
Supercat
@supercat Je ne suis pas sûr de bien comprendre votre quête. En termes d’application active, presque toute augmentation du temps d’exécution ou du nombre d’ios risque d’engendrer des blocages. ... Mais, plus précisément, la présence ou l'absence d'un index dans la plupart des applications est négligeable jusqu'à ce que la base de données atteigne une taille critique et / ou un niveau de concurrence. Par exemple, lorsque tous vos index ne tiennent plus dans la mémoire ...
svidgen
1
Le fait est qu'il est difficile de savoir quelle est la composition de votre requête jusqu'à ce que les cas d'utilisation typiques soient soumis à un test de contrainte (ou jusqu'à ce que vous voyiez des problèmes avec le comportement inattendu de l'utilisateur en production). Si vous avez une page qui se sépare de tablex.fieldy, mais qu'elle ne s'affiche qu'une fois pour mille inserts ... L'index peut entraîner une dégradation du réseau.
svidgen
2

Lorsque votre application est publiée, il est trop tard.

Mais tout processus de développement approprié devrait inclure des tests de performance.

Utilisez les résultats de vos tests de performance pour choisir les index à ajouter et vérifiez leur efficacité en répétant les tests de performance.

Philipp
la source
Quand une application est publiée, c'est vraiment le bon moment pour peaufiner les index. Regardez ce site, stachexchange, vous pouvez parier que les indices ont changé longtemps après sa mise en ligne.
LosManos
@ LosManos: Personne ne paie pour utiliser Stack Exchange.
Courses de légèreté avec Monica
@LightnessRacesinOrbit: Au contraire, les annonceurs paient pour utiliser Stack Exchange.
@JonofAllTrades: Ils ne se soucient pas de savoir si nous avons quelques heures de mauvaises performances en raison d'un index manquant. Ce que je veux dire, c’est qu’un grand site Web, gratuit et axé sur la communauté, avec un cycle de distribution perpétuel, est très différent d’un produit commercial autonome publié périodiquement. Ainsi, SE n'est pas un bon exemple.
Courses de légèreté avec Monica
1

Bien que je ne pense pas que toutes les requêtes doivent être optimisées, les index font tellement partie du SGBDR qu’ils doivent être pris en compte avant la publication. Lorsque vous exécutez une requête, contrairement aux autres formes de programmation, vous ne dites pas au système comment l'exécuter. Ils développent leurs propres plans et le basent presque toujours sur la disponibilité d'un index. La composition et le volume des données seront également pris en compte ultérieurement.

Voici quelques points à considérer:

  1. Il y a des questions que vous devez identifier dans votre développement initial et que vous savez être utilisées fréquemment. Concentrez-vous sur eux.
  2. Il y aura des requêtes lentes. En les indexant d'abord, vous pouvez ensuite déterminer si les performances ne sont toujours pas assez rapides, puis envisager une nouvelle conception (la dénormalisation peut être prématurée). Je préférerais le faire avant une sortie. Personne ne veut d'un système où il faut 10 minutes pour trouver quelque chose dans l'inventaire.
  3. Les index peuvent améliorer les performances des requêtes mais ne doivent pas entraver la modification des données.
  4. De nombreux systèmes ont des outils pour analyser vos requêtes, alors n’ayez pas peur de les utiliser.

Après votre examen initial, vous devez suivre quelques considérations pour savoir quand vous devez réexaminer ceci de nouveau et comment vous allez pouvoir collecter les informations à cette fin (surveiller l’utilisation, obtenir des copies des données du client, etc.).

Je réalise que vous ne voulez pas optimiser prématurément, mais il est presque certain que vos performances seront médiocres sans indexer votre base de données. En éliminant ce problème, vous pouvez déterminer s’il existe d’autres domaines qui posent des problèmes de performances.

JeffO
la source
0

Cela dépend également du nombre d'utilisateurs que vous attendez. Vous devez absolument faire des tests de charge et vous assurer que votre base de données peut suivre 10 à 100 à 1000 demandes simultanées. Encore une fois, cela dépend du trafic que vous attendez et des zones que vous prévoyez utiliser plus que d’autres.

En général, je voudrais ajuster les zones sur lesquelles l’utilisateur doit s’approcher le plus en premier. Ensuite, je réglerais tout ce qui est lent du point de vue de l'expérience utilisateur. Chaque fois que l'utilisateur doit attendre quelque chose, il a une mauvaise expérience et peut être refusé. Pas bon!

Harsimranb
la source
0

Il est recommandé d’identifier les colonnes qui ont définitivement besoin d’un index lors d’une analyse initiale. Il existe un risque réel de dégradation progressive ou imprévue des performances de la production lorsque la taille de la base de données augmente si vous n'avez absolument aucun index. La situation que vous souhaitez éviter est celle où une requête fréquemment exécutée nécessite d'analyser un grand nombre de lignes de table. Il n'est pas prématuré d'optimiser l'ajout d'indices aux colonnes critiques, car vous disposez de la plupart des informations nécessaires et dont les différences de performances potentielles sont importantes (ordres de grandeur). Il existe également des situations dans lesquelles l'avantage des indices est moins clair ou plus dépendant des données - vous pouvez probablement différer la décision pour certains de ces cas.

Certaines questions que vous devez poser sont les suivantes:

  • Quelles sont les limites de conception pour la taille de chaque table?

Si les tables doivent toujours être petites (disons <100 lignes), il ne s'agit pas d'un sinistre si la base de données doit analyser toute la table. Il peut être avantageux d’ajouter un indice, mais cela nécessite un peu plus d’expertise ou de mesure pour déterminer.

  • Quelle est la fréquence d'exécution de chaque requête et quel est le temps de réponse requis?

Si la requête est rarement exécutée et ne nécessite pas de temps de réponse strict (par exemple, la génération de rapports) et que le nombre de lignes n'est pas énorme, il est probablement relativement prudent de différer l'ajout d'index. Encore une fois, l'expertise ou la mesure peut aider à dire si cela va être bénéfique.

  • La requête nécessite-t-elle de regarder la table avec autre chose que la clé primaire? Par exemple, filtrer par plage de dates, joindre sur une clé étrangère?

Si ces requêtes sont exécutées fréquemment et touchent des tables comportant de nombreuses lignes, vous devez sérieusement envisager l’ajout préventif d’un index. Si vous n'êtes pas sûr que ce soit le cas pour une requête, vous pouvez renseigner la base de données avec une quantité réaliste de données, puis consultez le plan de requête.

utilisateur611910
la source