Y a-t-il un gain de performances lors de l'indexation d'un champ booléen?


103

Je suis sur le point d'écrire une requête qui inclut un fichier WHERE isok=1. Comme son nom l'indique, isokest un champ booléen (en fait un TINYINT(1) UNSIGNEDqui est défini sur 0 ou 1 selon les besoins).

Y a-t-il un gain de performances lors de l'indexation de ce champ? Le moteur (InnoDB dans ce cas) fonctionnerait-il mieux ou moins bien en recherchant l'index?


Réponses:


80

Pas vraiment. Vous devriez y penser comme un livre. S'il n'y avait que 3 types de mots dans un livre et que vous les indexiez tous, vous auriez le même nombre de pages d'index que les pages normales.

Il y aurait un gain de performance s'il y avait relativement peu d'enregistrements d'une valeur. Par exemple, si vous avez 1000 enregistrements et que 10 d'entre eux sont VRAI, il serait utile de rechercher avecisok = 1

Comme Michael Durrant l'a mentionné, cela ralentit également les écritures.

EDIT: duplication possible: indexation des champs booléens

Ici, il explique que même si vous avez un index, si vous avez trop d'enregistrements, il n'utilise pas l'index de toute façon. MySQL n'utilise pas l'index lors de la vérification de = 1, mais l'utilise avec = 0


4
On dirait "oui: 2 - non: 1". Quelqu'un a tort ici, mais qui?
Niet the Dark Absol

4
Ce n'est pas tout à fait correct, sans index, mySql doit parcourir toute la table pour trouver les lignes pertinentes.
ilanco

4
sinon, il balayerait tout l'index. (qui est tout aussi long dans la plupart des cas)
Michael Koper

1
Ca peut faire la différence. Il suffit de réduire de moitié le temps d'exécution d'une requête en ajoutant simplement un index, et les écritures sont assez rares et bon marché pour que nous ne nous soucions pas vraiment de la pénalité. Comme pour tout, ne supposez pas, ne mesurez pas (aussi parce que les bases de données ne se comportent pas toujours comme vous l'attendriez logiquement)
Eelco

6
Cela suppose une distribution égale entre VRAI et FAUX. Comme mentionné par @oucil ci-dessous, si vous recherchez une valeur booléenne assez rare, cela peut encore prendre un certain temps. Je ne dis pas que vous devez toujours indexer, mais je suppose que la nature de vos données et de vos requêtes importe également dans la plupart des moteurs de base de données.
mahemoff du

118

Juste pour mettre un point plus fin sur plusieurs autres réponses ici, car dans mon expérience, ceux qui examinent des questions comme celle-ci sont dans le même bateau que nous, nous avons tous entendu dire que l'indexation des champs booléens est inutile, et pourtant ...

Nous avons une table avec environ 4 millions de lignes, seulement environ 1000 à la fois auront un commutateur booléen marqué et c'est ce que nous recherchons. L'ajout d'un index sur notre champ booléen a accéléré les requêtes par ordre de grandeur, il est passé d'environ 9 secondes et plus à une fraction de seconde.


Oui, alors que vous devriez définitivement essayer de comprendre le `` pourquoi '' des choses, mesurez toujours et essayez différentes choses sur votre jeu de données réel pour voir si votre théorie correspond au comportement réel du moteur de base de données (vous seriez surpris ... )
Eelco

8
@Eelco Vous avez raison, mais dans ce cas, le résultat correspond bien à la théorie de base. L'idée de base selon laquelle il devrait être négligeable n'a de sens que si vous avez environ 50% de chances de trouver des éléments correspondant à votre recherche. Ensuite, pour trouver 100 correspondances, la base de données doit itérer 200 éléments. Mais si les éléments ne correspondent qu'à 1% du temps, il faudrait itérer 10 000 éléments.
mahemoff le

7
J'aime quand les gens essaient des choses sur le terrain et donnent des retours sur les gains de performance au lieu de simplement philosopher.
Viktor Joras

WHERE my_col > 0 au lieu de my_col = 1semble aussi aider à accélérer
Aaron

28

Cela dépend des requêtes réelles et de la sélectivité de la combinaison index / requête.

Cas A : condition WHERE isok = 1et rien d'autre ici:

SELECT *
FROM tableX
WHERE isok = 1
  • Si l'index est suffisamment sélectif (disons que vous avez 1M de lignes et seulement 1k en a isok = 1), alors le moteur SQL utilisera probablement l'index et sera plus rapide que sans lui.

  • Si l'index n'est pas assez sélectif (disons que vous avez 1M de lignes et plus de 100k en ont isok = 1), alors le moteur SQL n'utilisera probablement pas l'index et effectuera une analyse de table.

Cas B : état WHERE isok = 1et autres choses:

SELECT *
FROM tableX
WHERE isok = 1
  AND another_column = 17

Ensuite, cela dépend des autres index dont vous disposez. Un index sur another_columnserait probablement plus sélectif que l'index sur isoklequel n'a que deux valeurs possibles. Un index sur (another_column, isok)ou (isok, another_column)serait encore mieux.


Je pense que c'est la réponse la plus correcte par rapport à la première. également la distribution des données.
tyan le

12

Cela dépend de la distribution des données.

Imaginez que j'avais un livre avec 1000 pages étroitement dactylographiées, et les seuls mots de mon livre étaient «oui» et «non» répétés à plusieurs reprises et distribués au hasard. Si on me demandait d'encercler toutes les instances de «oui», un index à la fin du livre aiderait-il? Ça dépend.

S'il y avait une distribution aléatoire moitié-moitié des oui et des non, la recherche dans l'index n'aiderait pas. L'index rendrait le livre beaucoup plus gros, et de toute façon je serais plus rapide de commencer par le devant et de parcourir chaque page à la recherche de toutes les instances de `` oui '' et de les encercler, plutôt que de rechercher chaque élément dans l'index, puis en prenant la référence de l'entrée d'index à la page à laquelle elle fait référence.

Mais s'il n'y avait, disons, que dix instances de `` oui '' dans mon livre de mille pages et que tout le reste n'était que des millions de non, alors un index me ferait gagner beaucoup de temps pour trouver ces dix instances de `` oui '' et les encercler .

C'est la même chose dans les bases de données. Si c'est une distribution 50:50, alors un index ne va pas aider - le moteur de base de données est mieux de simplement parcourir les données du début à la fin (analyse complète de la table), et l'index ne ferait que agrandir la base de données, et plus lent à écrire et à mettre à jour. Mais si c'est quelque chose comme une distribution 4000: 1 (selon oucil dans ce fil), alors une recherche d'index peut l'accélérer énormément, si c'est le 1 sur 4000 éléments que vous recherchez.


5

Non, généralement pas.

Vous indexez généralement les champs pour la recherche lorsqu'ils ont une sélectivité / cardinalité élevée. La cardinalité d'un champ booléen est très faible dans la plupart des tables. Cela rendrait également vos écritures un peu plus lentes.


3

En fait, cela dépend des requêtes que vous exécutez. Mais, généralement oui, ainsi que l'indexation d'un champ de tout autre type.


2

Oui, un index améliorera les performances, vérifiez la sortie d'EXPLAIN avec et sans l'index.

À partir de la documentation:

Les index sont utilisés pour rechercher rapidement des lignes avec des valeurs de colonne spécifiques. Sans index, MySQL doit commencer par la première ligne, puis parcourir toute la table pour trouver les lignes pertinentes. Plus la table est grande, plus cela coûte cher. Si la table a un index pour les colonnes en question, MySQL peut rapidement déterminer la position à rechercher au milieu du fichier de données sans avoir à regarder toutes les données.

Je pense qu'il est également prudent de dire qu'un index ne DIMINUERA pas les performances dans ce cas, vous n'avez donc qu'à en tirer profit.


2
Un index donne beaucoup de données sur le disque dur et rend les écritures plus lentes afin que vous n'en tiriez pas que profit.
Michael Koper

1
C'est vrai, mais dans ce cas, une TINYINT(1) UNSIGNEDcolonne, la taille des données sera petite.
ilanco

Et la surcharge d'écriture ajoutée est probablement assez faible
Eelco

La taille de l'index ne va-t-elle pas augmenter avec le nombre de lignes vers lesquelles il pointe, pas seulement la taille du champ indexé?
poolie
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.