Comment les grands champs INCLUDE d'index affecteront-ils les performances du système?

15

Cette question concerne les performances de l'index SQL Server avec un varchar(2000)comme un INCLUDEdans un index de couverture.

J'essaie d'améliorer les performances dans une application de base de données lente et instable. Dans certains cas, les données sont accessibles par les grandes chaînes de varchar, avec les requêtes , y compris les opérations de chaîne multple comme SUBSTRING(), SPACE()et DATALENGTH(). Voici un exemple simplifié d'accès;

update fattable set col3 =  
   SUBSTRING(col3,1,10) + '*' + 
   SUBSTRING(col3,12,DATALENGTH(col3)-12)
from fattable where substring(col3,10,1) = 'A' and col2 = 2

Le schéma ressemble à ceci:

CREATE TABLE [dbo].[FatTable]( 
    [id] [bigint] IDENTITY(1,1) NOT NULL, 
    [col1] [nchar](12) NOT NULL, 
    [col2] [int] NOT NULL, 
    [col3] [varchar](2000) NOT NULL, ... 

L'index suivant a été défini, avec un champ couvrant sur la grande colonne de texte.

CREATE NONCLUSTERED INDEX [IndexCol2Col3] ON [dbo].[FatTable]  ( [col2] ASC ) 
    INCLUDE( [col3] )

D'après ce que j'ai lu, c'est MAUVAIS de mettre de grands champs de données dans un index. J'ai lu plusieurs articles, dont http://msdn.microsoft.com/en-us/library/ms190806.aspx qui discutent de l'impact de la pagination et de la taille du disque sur les performances de l'index. Cela étant dit, le plan de requête utilise définitivement l'index de couverture. Je n'ai pas suffisamment d'informations pour déterminer combien cela me coûte réellement en termes de charge système. Je sais que dans l'ensemble, le système fonctionne mal et je crains que ce soit l'un des problèmes. Des questions:

  • Mettre cette varchar(2000)colonne dans l'index INCLUDEest-il une bonne idée?

  • Étant donné que les INCLUDEchamps sont stockés dans des nœuds feuilles, ont-ils beaucoup de performances d'index d'impact?

Mise à jour: Merci pour les excellentes réponses! C'est une question injuste à certains égards - comme vous le dites, il n'y a pas de bonne réponse absolue sans statistiques et profilage réels. Comme tant de problèmes de performances, je suppose que la réponse est "cela dépend".

RaoulRubin
la source
Quelle est la durée des valeurs réelles? Un VARCHAR(2000)qui ne stocke généralement que dix caractères est une chose; un solide 2000 octets par enregistrement est autre chose.
Jon of All Trades
Juste une observation: quelque chose qui "sent" ici est que la grande colonne peut contenir soit 1) du texte libre, auquel cas les requêtes peuvent bénéficier de réécritures pour utiliser un index FULLTEXT ou 2) des données codées "lisibles par l'homme" (par exemple, Wide Intelligent clés, comme un VIN) qui pourraient bénéficier de la division en colonnes distinctes ou de colonnes calculées persistantes avec INDEX. En d'autres termes, le flux d'intelligence et les changements de données ne sont pas bien conçus.
Graeme
1
Oui #Graeme, il y a une mauvaise odeur ici - je pense que cela s'appelle "héritage". Il y a une multitude de problèmes dans ces bases de données.
RaoulRubin

Réponses:

14

Ever est un grand mot, mais, en général, non, je ne mettrais pas un champ varchar (2000) dans un INCLUDE.

Et oui, la façon dont les données sont stockées au niveau de la page peut sérieusement affecter les performances de l'index, selon la façon dont l'index est utilisé.

Le fait est que plus vous pouvez insérer de lignes de données dans une page, moins vous devez accéder à des pages, plus votre système est rapide, pour la plupart. L'ajout d'une colonne très volumineuse signifie moins d'informations stockées sur une page.Par conséquent, en cas de recherche ou de numérisation de plage, davantage de pages doivent être lues pour récupérer les données, ce qui ralentit considérablement les choses.

Pour savoir avec certitude s'il s'agit d'un problème sur votre requête ou sur votre système, vous devez surveiller les lectures, en particulier le nombre de pages utilisées par la requête.

Grant Fritchey
la source
Merci Grant. Comme je l'ai mentionné un autre commentaire, les bonnes informations sur les performances sont rares, d'où la question abstraite. Je n'ai pas d'expérience dans la surveillance des coûts de performances de taille de page. Mon intuition est que c'est un problème, je vais voir si je peux obtenir des statistiques.
RaoulRubin
1
l'activation des statistiques IO pour la requête vous en dira beaucoup, les lectures logiques représentent le nombre de pages consultées. Vous pouvez également surveiller les secondes / lire à partir des compteurs perfmon pour obtenir des informations générales sur les performances.
Grant Fritchey
6

Pouvez-vous revoir la clé d'index en cluster actuelle et peut-être créer col2la clé d'index en cluster à la place? De cette façon, vous obtenez le comportement «inclure» de la couverture (puisque les indices groupés incluent toujours «tout») sans dupliquer les données. Ceci, bien sûr, est sujet à de nombreux ifet but, peut-être, mérite néanmoins d'être considéré. Bien sûr, si l'index cluster actuel applique une contrainte (clé primaire, unique), cette contrainte devra être déplacée dans un index non cluster.

Remus Rusanu
la source
Votre suggestion sur le PK est une excellente idée, bien que je ne puisse pas l'appliquer dans ce cas - le PK existant est nécessaire pour d'autres requêtes. (C'est une technique que je garderai dans la boîte à outils!)
RaoulRubin
4

Il est difficile de répondre. Tout dépendra de votre rapport lecture / écriture. Avez-vous testé une charge de travail ou simulé un cycle commercial complet sur un système de test, avec et sans la colonne incluse? La recherche sans cela peut coûter cher, mais si vous mettez à jour les données plus souvent que vous ne les lisez, cela pourrait être correct.

Aaron Bertrand
la source
La lecture globale par rapport à la mise à jour est généralement équilibrée. Les problèmes d'organisation et de confidentialité rendent difficile l'obtention de statistiques utiles et de tests réalistes. Puisque nous volons principalement à l'aveugle, nous devons regarder les choses d'un point de vue abstrait (d'où cette question). Les tests signifieront pousser des changements dans la production et observer les résultats - très risqué.
RaoulRubin
2
Et la plupart des lectures tirent-elles réellement cette VARCHAR(2000)colonne, ou dépannez-vous les performances d'une requête très spécifique qui ne représente pas la plupart des requêtes? Comme Grant le suggère si cette colonne n'est pas utilisée dans un grand nombre de requêtes, ou cause vraiment des problèmes pour les recherches, il sera probablement préférable de payer le prix de la recherche lorsque vous en avez besoin, mais de ne pas payer le stockage lorsque vous ne le faites pas. . Encore une fois, il est vraiment difficile de dire de quel côté de la clôture vous devriez être, car nous n'avons pas vraiment de détails (et encore plus difficile parce que vous ne pouvez pas tester - vous devriez vous efforcer de résoudre ce problème).
Aaron Bertrand
3

Je sais que je suis en retard pour cette fête, mais j'indexerais exactement les expressions utilisées pour localiser les lignes, telles que la sous-chaîne (col3,10,1). Si le col3 entier est utilisé, j'indexerais CHECKSUM (col3) (en comprenant bien sûr qu'il pourrait y avoir des collisions).

AK
la source