Si une base de données n'a jamais qu'un insert, est-il mauvais d'indexer toutes les combinaisons de colonnes possibles?

23

Je travaille sur un système de rapports qui nécessitera de grandes requêtes sélectionnées, mais est basé sur une base de données qui n'est remplie qu'une seule fois. Le système de gestion de base de données est Microsoft SQL Server 2017. Il existe probablement une meilleure façon de concevoir un système comme celui-ci, mais abordons cela théoriquement.

Théoriquement parlant:

  1. Si nous avons une très grande base de données (150M + lignes sur plusieurs tables)
  2. Et nous pouvons supposer que la base de données ne sera remplie qu'une seule fois.

L'indexation de chaque combinaison de colonnes possible peut-elle avoir un impact négatif sur les performances d'une requête sélectionnée?

De guingois
la source
4
Chaque combinaison possible n'est pas pratique la plupart du temps. Une approche plus sensée consiste à indexer manuellement mais de manière très généreuse. Cela peut certainement avoir du sens.
usr
12
Je suggère de reformuler votre titre ou votre texte en gras afin qu'ils soient cohérents. En un coup d'œil, j'ai été confus par la réponse la plus élevée «oui»
aaaaaa
150 millions de lignes sont grandes pour une seule table, mais pas grandes pour une base de données. En pratique, les systèmes de génération de rapports n'utilisent qu'un petit sous-ensemble de combinaisons de colonnes possibles, il est préférable de se concentrer sur les combinaisons de touches au moins initialement, puis de devenir plus complexe uniquement si nécessaire.
pojo-guy

Réponses:

36

Oui, cela influencera le temps de compilation du plan initial car l'optimiseur aura de nombreux chemins d'accès supplémentaires aux données à considérer.

Étant donné que vous utilisez SQL Server 2017, que vous chargez une fois et exécutez des rapports, pourquoi ne pas simplement utiliser un index de stockage de colonnes en cluster à la place?

Cela semble être la solution idéale à votre besoin d'indexer toutes les combinaisons de colonnes possibles.

Index de colonnes - Présentation

Erik Darling
la source
Columnstore est l'endroit où j'irais aussi, mais je me demande simplement ... l'optimiseur ne fonctionne-t-il pas exactement le contraire de ce que vous avez décrit? Je veux dire au lieu de balayer les index disponibles et de "se demander" lequel d'entre eux pourrait être utile n'est-ce pas egzamin la requête et "pensez-vous" à un index parfait pour cette requête, alors il vérifie s'il existe? (Si ce n'est pas le cas, un message d'index manquant est généré.) Si j'ai raison (je ne sais pas, je suppose), même s'il y a des milliers d'index, cela ne devrait pas être beaucoup plus long que d'en avoir plusieurs d'eux.
Limonka
26

Si vous avez N colonnes dans une table, chaque combinaison de colonnes possible est 2 ^ N-1 (en supprimant l'ensemble vide). Pour 10 colonnes, cela signifierait 1023 index, pour 20 colonnes, nous nous retrouvons avec un énorme 1048575 index. La plupart des index ne seront jamais utilisés mais devront être pris en compte par l'optimiseur. Il est possible que l'optimiseur choisisse un indice sous-optimal au lieu d'un meilleur. Je ne prendrais pas le chemin de la génération de toutes sortes d'index, au lieu d'essayer de comprendre quels index seraient réellement bénéfiques.

EDIT corrigé le nombre d'index possibles

Comme Jeff le souligne, c'est encore pire que 2 ^ N (power-set) car (3,2,1) est clairement différent de (1,2,3). Pour N colonnes, nous pouvons choisir la première position dans un index qui contient toutes les colonnes de N façons. Pour la deuxième position en N-1, etc. On se retrouve donc avec N! différents index de taille réelle. Aucun de ces index n'est subsumé par un autre index de cet ensemble. De plus, nous ne pouvons pas ajouter un autre index plus court afin qu'il ne soit couvert par aucun index complet. Le nombre d'index est donc N !. L'exemple pour 10 colonnes devient donc 10! = 3628800 index et pour 20 (drumroll) 2432902008176640000 index. C'est un nombre ridiculement élevé, si nous mettons un point pour chaque index un mm par pièce, il faudra un faisceau lumineux 94 jours pour passer tous les points. De toute façon, non ;-)

Lennart
la source
6
Pire encore: l'ordre des colonnes dans l'index peut être important. Vous obtenez donc un maximum de N! index.
Jeff
2
Mais vous n'avez pas besoin d'index qui sont des préfixes d'autres index.
Barmar
3
C'est encore pire. Il existe des combinaisons ASC et DESC pour chaque index.
ypercubeᵀᴹ
2
Et bien pire, il existe des index INCLUDE.
ypercubeᵀᴹ
2
Et un grand nombre d'index partiels.
ypercubeᵀᴹ
7

Non.

Il n'est pas pratique d'indexer "tout", mais vous pouvez en indexer "la plupart".

Voici le truc. Si une table a des Ncolonnes, le nombre d'index possibles est N!. Disons qu'une table a 10 colonnes, alors vous avez non seulement 10des index possibles, mais 10!. C'est ... 3 628 800 ... sur une seule table. Cela représente beaucoup d'espace disque, d'E / S disque, de cache et de temps de recherche.

Pourquoi? Quelques raisons:

  • Les index Lightwwight sont généralement mis en cache, ce qui les rend rapides à éclairer. Si vous en avez 3 millions, ils ne seront PAS mis en cache.

  • L'optimiseur SQL peut prendre beaucoup de temps pour décider lequel est préférable d'utiliser, en particulier lors de l'utilisation de jointures.

  • L'optimiseur SQL peut abandonner l'utilisation de l'algorithme complet et essayer un algorithme heuristique à la place. Cela peut être "moins qu'optimal". PostgreSQL, par exemple, propose différentes options pour les "requêtes de table inférieures à 8" et les "requêtes de table supérieures à 8".

  • Les index sont censés être plus légers que le tas. Si vous indexez tout, alors l'index devient aussi lourd que le tas ... quelque chose qui va à l'encontre de l'objectif de l'index.

L'Impaler
la source
N'est-ce pas le nombre 2 ^ 10? Chaque colonne est incluse ou exclue d'un index donné. La commande est-elle importante?
RemcoGerlich
2
@RemcoGerlich oui, la commande est importante.
ypercubeᵀᴹ
2

Non, cela n'aura probablement pas d'impact négatif sur les SELECTrequêtes, mais

  • Cela entraînera une utilisation élevée du disque.
  • Cela augmentera considérablement les INSERTcoûts.
  • La plupart de vos indices ne seront jamais utilisés.
  • De nombreuses WHEREexpressions de condition n'utilisent toujours pas d'indices, principalement les plus complexes.
  • Le nombre d'indices requis augmentera de façon exponentielle avec le nombre de colonnes. Autrement dit, si vous avez, par exemple, 8 colonnes, vous avez besoin de 256 indices pour toutes les combinaisons possibles.
peterh dit réintégrer Monica
la source
Cela peut totalement causer un problème au moment de la compilation.
Erik Darling
@sp_BlitzErik Pensez-vous à l'ORM dans l'application?
Peterh dit de réintégrer Monica le
Non, voyez ma réponse.
Erik Darling
@sp_BlitzErik Wow, agréable à voir!
peterh dit réintégrer Monica le