85 votes

Indéxer les champs booléens

Y aura-t-il beaucoup d'avantages à indexer un champ booléen dans une table de base de données ?

Dans une situation courante, comme les enregistrements "soft-delete" qui sont marqués comme inactifs, et donc la plupart des requêtes incluent WHERE deleted = 0, serait-il utile d'indexer ce champ seul, ou devrait-il être combiné avec les autres champs souvent recherchés dans un index différent ?

0 votes

32 votes

@AmirAliAkbari: Oh! Non! Une référence circulaire! Espérons que S.O. n'explosera pas!

2 votes

ATTENDS! Celui-ci existait en premier! L'autre a été créé après, ce qui signifie que celui-ci n'est PAS un doublon. S.O. est sauvé!

60voto

Mark Canlas Points 4698

Non.

Vous indexez des champs qui sont recherchés et qui ont une haute sélectivité / cardinalité. La cardinalité d'un champ booléen est oblitérée dans presque n'importe quelle table. Si quoi que ce soit, cela ralentira vos écritures (de manière infime).

Peut-être que vous pourriez en faire le premier champ de l'index clusterisé si chaque requête tenait compte des suppressions douces?

9 votes

Imaginez un grand livre avec des milliers de pages. Les pages contiennent une seule lettre, 'A' ou 'B' et un nombre aléatoire. Auriez-vous un avantage à trouver une certaine entrée de nombre aléatoire pour laquelle vous savez qu'elle est sur l'une des pages 'A' lorsque les pages A et B ne sont pas mélangées mais que le livre commence par des pages A seulement et ensuite B? Oui vous auriez.. donc je suppose que vous avez tort..

2 votes

Êtes-vous sûr que c'est correct? Je pourrais facilement voir qu'un tel champ a de la valeur si, par exemple, 99% du temps la valeur était 'non' et que vous n'interrogiez que les valeurs 'oui'. (Par exemple, seuls les enregistrements actifs?)

4 votes

Je pense que la réponse est trop simpliste, étant donné de nombreuses autres stratégies d'indexation dans les bases de données modernes. Par exemple, un index partiel WHERE field = false, ou certains autres index non-btree qui sont généralement spécifiques à la plate-forme, offrent des alternatives à un btree pour rechercher des booléens. Cela dépend également de vos conditions de recherche et de la proportion de la table qui est vraie par rapport à fausse.

18voto

jhlllnd Points 540

Qu'en est-il d'une colonne DATETIME deleted_at? Il y a deux avantages.

  1. Si vous avez besoin d'une colonne unique comme le nom, vous pouvez créer et supprimer en douceur un enregistrement avec le même nom plusieurs fois (si vous utilisez un index unique sur les colonnes deleted_at ET nom)
  2. Vous pouvez rechercher des enregistrements récemment supprimés.

Votre requête pourrait ressembler à ceci :

SELECT * FROM xyz WHERE deleted_at IS NULL

7voto

Brimstedt Points 1507

Je pense que cela aiderait, en particulier en ce qui concerne les indices.

La quantité/la quantité est bien sûr fonction de vos données et de vos requêtes.

Vous pouvez avoir toutes sortes de théories sur les index mais les réponses finales sont données par le moteur de base de données dans une base de données avec de vraies données. Et souvent, vous êtes surpris par la réponse (ou peut-être que mes théories sont trop mauvaises ;)

Examinez le plan de requête de vos requêtes et déterminez si les requêtes peuvent être améliorées, ou si les indices peuvent être améliorés. Il est assez simple de modifier les index et de voir quelle différence cela fait.

3 votes

@OMGPonies Le préjudice réside dans les frais supplémentaires d'écriture, sur une table très fréquentée avec beaucoup de lignes, cela peut réellement réduire les performances des requêtes. Ce n'est bénéfique que lorsque la cardinalité est élevée et que les requêtes sont conçues pour en tirer avantage.

2voto

umar Points 1427

Je pense que si votre champ booléen est tel que vous vous y référeriez dans de nombreux cas, il serait logique d'avoir une table séparée, par exemple DeletedPages, ou SpecialPages, qui auront de nombreux champs de type booléen, tels que is_deleted, is_hidden, is_really_deleted, requires_higher_user etc, et ensuite vous feriez des jointures pour les obtenir.

Typiquement, la taille de cette table serait plus petite et vous obtiendriez un avantage en faisant des jointures, surtout en ce qui concerne la lisibilité et la maintenabilité du code. Et pour ce type de requête :

sélectionnez toutes les pages où is_deleted = 1

Il serait plus rapide de l'implémenter comme ceci :

sélectionnez toutes les pages où les pages 
font une jointure avec DeletedPages sur page.id=deleted_pages.page_id

Je pense avoir lu quelque part à propos des bases de données mysql qu'il faut qu'un champ ait une cardinalité d'au moins 3 pour que l'indexation fonctionne sur ce champ, mais veuillez confirmer cela.

2 votes

Il est difficile de dire étant donné qu'un booléen est si mince et nous n'avons aucune donnée, mais encourir une jointure et son flux de travail à chaque requête rendrait les requêtes plus lentes, et non plus rapides, surtout si les clés primaires étaient regroupées différemment et si la table deleted_pages était nécessaire pour chaque requête.

2voto

astander Points 83138

Je pense que cela aiderait si vous utilisiez une vue (où supprimé = 0) et que vous interrogez régulièrement à partir de cette vue.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X