Quel est l'effet du remplacement des index par des index filtrés (valeur non nulle)?

10

Notre projet gère une très grande base de données très compliquée. Il y a environ un mois, nous avons remarqué que l'espace utilisé par les colonnes indexées contenant des valeurs nulles devenait trop grand. En réponse à cela, j'ai écrit un script qui rechercherait dynamiquement tous les index à colonne unique contenant plus de 1% de valeurs nulles, puis supprimerait et recréerait ces index en tant qu'index filtrés à condition que la valeur ne soit PAS NUL. Cela supprimerait et recréerait des centaines d'index dans la base de données et libérerait généralement près de 15% de l'espace utilisé par l'ensemble de la base de données.

Maintenant, j'ai deux questions à ce sujet:

A) Quels sont les inconvénients de l'utilisation d'index filtrés de cette manière? Je suppose que cela ne ferait qu'améliorer les performances, mais y a-t-il des risques de performances impliqués?

B) Nous avons reçu des erreurs ( 'impossible de supprimer l'index XYZ car il n'existe pas ou vous n'avez pas la permission' ) lors de la suppression et de la recréation des index, même si, après vérification, tout s'est déroulé exactement comme prévu. Comment cela peut-il arriver?

Merci pour toute aide!

Edit: En réponse à @Thomas Kejser

Salut et merci, mais il s'est avéré que c'était un désastre. À l'époque, nous ne comprenions pas plusieurs choses telles que:

  1. Lors d'une requête, SQLOS crée des plans d'index avant de déterminer qu'il ne peut pas utiliser de valeurs NULL pour joindre des colonnes de table. IE, vous avez vraiment besoin d'un filtre de clause WHERE ajustant l'index pour chaque index filtré utilisé dans la requête, sinon l'index ne sera pas utilisé du tout.
  2. La suppression et la création d'index et la mise à jour redondante de leurs statistiques une fois de plus par la suite peuvent ne pas suffire pour produire les plans mis à jour, ce que nous supposions. Il semble que dans certains cas, seule une charge de travail suffisamment élevée obligera SQL Server à réévaluer les plans.
  3. Il existe des éléments exotiques dans la fonctionnalité du planificateur d'exécution qui sont difficiles à déterminer par le seul bon sens et la seule logique. Avec des milliers de variations générées par le code de différentes requêtes, des index apparemment inutiles peuvent aider dans certaines statistiques et plans de requête qui finissent par être utilisés dans des requêtes critiques.

Finalement, ces changements ont été annulés. Les index filtrés sont donc un outil puissant, mais vous devez vraiment comprendre exactement quelles données sont extraites de ces colonnes. Là où les index normaux mis à part les problèmes d'espace sont plutôt faciles à appliquer, les index filtrés représentent des solutions très personnalisées. Ils ne remplacent certainement pas un index régulier, mais plutôt une extension de ceux-ci dans les circonstances particulières dont ils ont besoin.

Kahn
la source
Vous pouvez également revoir votre stratégie d'indexation. Si vous avez des centaines d'index à champ unique, ce n'est probablement pas optimal.
JNK
Leur besoin vient du fait que la base de données est partiellement héritée d'un autre système. Par défaut, nous avons des tables abstraites et plusieurs colonnes abstraites qui peuvent ne pas être utilisées du tout, ce qui produit la plupart de ces quantités massives de valeurs NULL indexées. Quant aux index à champ unique, ils sont créés à partir de l'exigence de base que chaque clé étrangère doit être indexée, et beaucoup d'entre eux se trouvent dans ces colonnes qui contiennent principalement ou uniquement des valeurs NULL.
Kahn

Réponses:

8

Approche très intéressante. Mon vote positif pour la créativité.

Depuis que vous avez récupéré l'espace, je suppose que les index d'origine ne sont plus en place? Les inconvénients des index filtrés sont alors:

  • Un trop grand nombre d'entre eux peut entraîner une augmentation trop importante de l'espace de recherche de l'optimiseur, ce qui entraîne des plans de requête médiocres lorsque l'optimiseur arrive à expiration.
  • Il existe plusieurs situations où un index filtré ne sera même pas pris en compte, même si l'équivalent non filtré le serait. Cela peut notamment se produire lorsque vous obtenez une jointure de hachage sur la colonne indexée ou si vous essayez de COMMANDER PAR la colonne (sans filtre)
  • Le paramétrage des requêtes ne fonctionne pas avec les index filtrés (voir: http://www.sqlservercentral.com/blogs/practicalsqldba/2013/04/08/sql-server-part-9-filtered-index-a-new-way- for-performance-improvemnt / )

En termes pratiques, cela signifie que vous devez être extrêmement prudent avec les index filtrés car ils entraîneront souvent d'horribles plans de requête. Je n'irais pas jusqu'à les qualifier d'inutiles, mais je les considère comme un ajout aux index traditionnels, pas comme un remplacement (comme vous essayez de le faire).

Thomas Kejser
la source
Msgstr "Le paramétrage des requêtes ne fonctionne pas avec les index filtrés". cela peut probablement être corrigé avec l'option (recompiler)
MichaelD
2

Thomas Kejser répond à ce sujet bien au-dessus.

J'ai juste pensé à ajouter 2 cents.

J'ai vu certains index filtrés uniquement utilisés (affichés dans le plan d'exécution) lorsque vous faites correspondre exactement la clause where de votre requête à celle de l'index filtré.

avez-vous essayé d'utiliser des vues indexées ? colonnes éparses ?

Je crois que dans la mesure où vous n'avez que des articulations internes, vous pouvez créer une vue indexée contenant la ou les clauses where de vos index filtrés, puis vous pouvez utiliser la vue à la place.

Il pourrait y avoir plusieurs vues. Mais comme pour les index non clusterisés, trop nombreux ralentiront votre écriture.

D'après mon expérience, vous auriez de bons gains en lecture, mais vous auriez à surveiller les écritures (insertions et mises à jour) spécialement si les tables sont impliquées dans la réplication.

Cependant, si je comprends bien votre principale préoccupation, the null valuesje vous suggère par conséquent des colonnes SPARSE dans vos index .

Les colonnes éparses sont particulièrement appropriées pour les index filtrés

Comme j'ai annoncé des colonnes clairsemées, je ne me sentirais pas bien si je ne vous parlais pas non plus de ses limites:

Lors de la conception de tables avec des colonnes éparses, n'oubliez pas que 2 octets supplémentaires de surcharge sont requis pour chaque colonne éparse non nulle de la table lorsqu'une ligne est mise à jour.

À la suite de cette

mémoire supplémentaire requise, les mises à jour peuvent échouer de manière inattendue avec l'erreur 576 lorsque la taille totale des lignes, y compris cette surcharge de mémoire, dépasse 8019,

et aucune colonne ne peut être poussée hors de la ligne.

Prenons l'exemple> d'une table qui a 600 colonnes éparses de type bigint.

S'il y a 571 colonnes non nulles, la taille totale sur le disque est de 571 * 12 = 6852 octets. Après avoir inclus la surcharge de ligne supplémentaire et l'en-tête de colonne éparse, cela augmente à environ 6895 octets. La page a encore environ 1124 octets disponibles sur le disque. Cela peut donner l'impression que des colonnes supplémentaires peuvent être mises à jour avec succès. Cependant, pendant la mise à jour, il y a une surcharge supplémentaire en mémoire qui est 2 * (nombre de colonnes éparses non nulles). Dans cet exemple, l'inclusion de la surcharge supplémentaire - 2 * 571 = 1142 octets - augmente la taille des lignes sur le disque à environ 8037 octets. Cette taille dépasse la taille maximale autorisée de 8019 octets. Étant donné que toutes les colonnes sont des types de données de longueur fixe, elles ne peuvent pas être repoussées hors de la ligne. Par conséquent, la mise à jour échoue avec l'erreur 576.

plus de détails sur le lien ci-dessus, cependant je préfère poster ici aussi cet avertissement:

La modification d'une colonne de clairsemée à non clairsemée ou non clairsemée à clairsemée nécessite de modifier le format de stockage de la colonne.

Le moteur de base de données SQL Server utilise la procédure suivante pour effectuer cette modification:

1 - Ajoute une nouvelle colonne à la table dans la nouvelle taille et le nouveau format de stockage.

2 - Pour chaque ligne du tableau, met à jour et copie la valeur stockée dans l'ancienne colonne vers la nouvelle colonne.

3 - Supprime l'ancienne colonne du schéma de table.

4 - Reconstruit la table (s'il n'y a pas d'index cluster) ou reconstruit l'index cluster pour récupérer l'espace utilisé par l'ancienne colonne.

Marcello Miorelli
la source
1
Salut. Un peu en retard mais oui, alors que nous avons abandonné l'approche décrite dans ce sujet il y a longtemps, nous y sommes récemment revenus avec une approche plus sélective. Fondamentalement, nous avons examiné l'utilisation des statistiques et le modèle commercial pour confirmer les indices table par table. Ensuite, il l'a testé en ajoutant un nouvel index filtré du côté de l'index normal, et a vérifié pour voir pendant quelques semaines celui qui a finalement été utilisé. Après avoir confirmé que SEULEMENT les index filtrés ont été utilisés dans les nouveaux plans, nous avons abandonné les index normaux non filtrés.
Kahn
1
De plus, nous avons changé pas mal de colonnes en types clairsemés. Le problème avec cela, cependant, est que, comme vous le verrez dans MSDN, la modification d'un type de colonne à faible force essentiellement la recréation de tout l'index clusterisé. Rendre cela plutôt lourd pour les grandes tables complexes. Nous avons donc renommé les contraintes et la table, créé une nouvelle avec le même modèle et le même nom d'origine mais avec des colonnes éparses, puis transféré les données dans la nouvelle table par lots appropriés. Puis une fois vérifié que tout allait bien et que tous les index et FK étaient à nouveau en place, les anciennes tables ont été supprimées.
Kahn
1
De plus, dans certains cas, l'utilisation de la compression de page était de loin préférable, nous avons donc fini par le faire à la place. C'est également pratique car vous pouvez simplement créer l'index en cluster existant avec DROP_EXISTING = ON, pour le rendre beaucoup, beaucoup plus rapide que la route clairsemée. D'autant plus que cela évite les tracas de la nouvelle gestion des index et des FK.
Kahn