L'ajout d'index sur la colonne de bits ralentit-il considérablement les insertions?

11

J'ai une table avec environ 1 à 5 millions d'enregistrements. Une petite partie de ces enregistrements a une colonne de bits définie sur «VRAI». Besoin de trouver rapidement ces enregistrements. Je pense que l'index peut accélérer la recherche sur cette colonne, mais j'ai peur des INSERT. D'où ma question.

La base de données fonctionne comme une sorte d'entrepôt de données, il y a donc de nombreux SELECT et de petits INSERT (jusqu'à 10-20 par jour) mais assez grands (jusqu'à 200 000 enregistrements à la fois). J'ai peur du temps plus long de ces importations dans la base de données.

marioosh
la source
5
Quelle version de SQL Server? Si 2008+ sonne comme un index filtré, cela pourrait être ce dont vous avez besoin.
Martin Smith
SQL Server 2005
marioosh
1
Vous pouvez diviser la table (ajouter une nouvelle table avec une seule colonne, le PK de la table, qui serait rempli uniquement avec les lignes sur lesquelles la colonne de bits est vraie - à la fin, vous pourriez même supprimer la colonne de bits.) Cette vue fonctionnerait, également en 2005, avec l’absence d’indices partiels.
ypercubeᵀᴹ
soyez prudent avec la vue indexée, comme vous l'avez mentionné, vous disposez de 10 à 20 gros insert par jour, la maintenance de la vue indexée peut dépasser l'avantage du gain de performances. Je ne pense pas que "la fonctionnalité prête à l'emploi" de SQL 2005 puisse être utilisée pour améliorer votre situation. mais si vous listez la structure actuelle de la table et l'index existant, nous pouvons trouver une autre conception.
Anup Shah

Réponses:

8

Un index sur un bit pour 1 million d'enregistrements est inutile. L'optimiseur ne l'utilisera jamais, vous ne payez que pour le maintenir. Une bien meilleure alternative consiste à ajouter ce bit comme clé la plus à gauche sur l'index clusterisé.

Mais je vais faire un tir aveugle dans l'obscurité et deviner que ce que vous avez est un modèle de file d'attente: les enregistrements sont déposés dans la table avec le bit défini sur 'TRUE' (c'est-à-dire 'needsprocessing = true'), puis un processus d'arrière-plan semble pour ces enregistrements, effectue un certain traitement et met à jour le bit sur FALSE. Il s'agit d'un modèle omniprésent, également connu sous le nom de «modèle de recette de catastrophe de performance». Je recommanderais de déposer les enregistrements dans la table et de déposer une notification (pourrait être aussi simple que l'ID d'enregistrement nouvellement inséré), en même temps, dans une file d'attente . Voir Utilisation de tables comme files d'attente .

Remus Rusanu
la source
1
Je ne vois aucun bon point à mettre la colonne de bits sur le côté le plus à gauche car nous ne savons pas que d'autres colonnes de filtre avec un utilisateur à cardinalalité élevée peuvent avoir. Jusqu'à présent, j'ai vu la colonne BIT est le dernier choix dans l'index cluster. mais oui, +1 pour la belle référence de "Utilisation de la table comme files d'attente".
Anup Shah
2
En fait, j'ai exécuté un test et oui, il utilisera l'index. Créez une table (identité d'identité, bit myBit), ajoutez 100 lignes où le bit est 0 et 2000000 où le bit est 1. Assurez-vous que les statistiques sont mises à jour (si nécessaire) et exécutez une requête sur myBit = 0 et l'index sera utilisé.
Kenneth Fisher
@KennethFisher sauf que dans le modèle typique de haute vitesse d'insertion VRAI / mise à jour à FAUX immédiatement les statistiques seront toujours obsolètes. Si vous préférez jouer à la roulette russe avec l'optimiseur plutôt que de faire un design clair, vous obtiendrez ce que vous méritez ...
Remus Rusanu
"ne l'utilisera jamais", cette affirmation vaut pour 99% des cas, mais nous ne savons pas dans quel cas se trouve l'OP. J'ai réussi à indexer un peu. Des cas d'utilisation existent.
usr
question - la réponse ici est-elle fausse, en particulier> "Lorsque vous indexez un champ de bits (ou une plage étroite), vous ne réduisez le jeu de travail que par le nombre de lignes correspondant à cette valeur. Si vous avez un petit nombre de lignes correspondant réduirait considérablement votre ensemble de travail . Pour un grand nombre de lignes avec une distribution 50/50, cela pourrait vous faire gagner très peu de performances par rapport à la mise à jour de l'index. " Dans ce cas, un index sur un bit qui correspond à 1% des enregistrements éviterait la nécessité de scanner 99% de 1 million pour un boost significatif?
drzaus
2

Comme l'a dit @MartinSmith, si vous effectuez une mise à niveau vers SQL 2008, un index filtré serait la solution parfaite. Cependant, dans le même temps, comme un cas général, TOUT index ajouté augmentera votre temps de chargement. Les petits index le sont moins que les grands.

Une chose que je regarderais est si vous avez un index existant qui peut être modifié. En supposant que vos requêtes existantes utilisent un index donné, l'ajout de la colonne de bits à la fin de cet index devrait avoir un effet minimal sur les insertions et l'effet positif que vous recherchez sur vos requêtes.

La prochaine chose à regarder est "Dois-je déjà beaucoup d'index?" Il n'y a pas de règle stricte quant à ce qu'est "beaucoup", mais j'utilise généralement une règle de 10 index, c'est la limite, sauf si j'en ai VRAIMENT besoin d'un nouveau.

Dernière pensée, testez-le sur une instance de test. Configurez une table avec quelques millions de lignes, exécutez votre charge dessus, ajoutez votre index puis réexécutez votre charge et voyez si vous remarquez une augmentation significative du temps de chargement.

Vous seul pouvez vraiment décider de ce qui est «significatif». J'ai des machines où l'ajout de 5 minutes au temps de chargement est "significatif" et d'autres où je pouvais voir en toute sécurité une augmentation de quelques heures.

ÉDITER:

Une autre option consiste à partitionner votre table. Vous devrez peut-être utiliser une vue partitionnée si vous n'utilisez pas l'édition Enterprise, mais cela devrait néanmoins vous aider. Vous mettez vos bits 0 dans une partition et vos bits 1 dans une autre. En supposant que vous n'insérez qu'une version ou l'autre, vous pouvez même accélérer vos insertions.

Kenneth Fisher
la source