Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Composants internes de SQL Server :Opérateurs problématiques Pt. I – Numérisations

SQL Server existe depuis plus de 30 ans, et je travaille avec SQL Server depuis presque aussi longtemps. Kalen couvre les analyses dans la première partie de SQL Server Internals :Opérateurs problématiques.

J'ai vu beaucoup de changements au fil des années (et des décennies !) et des versions de cet incroyable produit. Dans ces articles, je vais partager avec vous comment j'examine certaines des fonctionnalités ou certains aspects de SQL Server, parfois avec un peu de perspective historique.

Le réglage de vos requêtes SQL Server est l'une des meilleures choses que vous puissiez faire pour améliorer les performances et optimiser les diagnostics du serveur SQL. Mais le tuning est un vaste sujet ! Savoir exactement comment régler de la meilleure manière possible nécessite non seulement une connaissance approfondie de vos données et de votre charge de travail, mais également une connaissance de la manière dont SQL Server fait réellement ses choix d'exécution de plan. Alors, que pouvez-vous faire si vous n'êtes pas un expert en interne de SQL Server ? Une chose que vous pouvez faire est de vous fier à des experts, ainsi qu'à des outils écrits par des experts. Des outils tels que Quest Spotlight Cloud Tuning Pack peuvent vous donner d'excellentes suggestions pour commencer à améliorer les performances des requêtes. Bien sûr, aucun outil externe ne connaît vos données et tous les détails de toutes vos charges de travail, il est donc toujours recommandé de tester en profondeur toute suggestion que vous décidez de mettre en œuvre.

Dans ces articles sur les opérateurs problématiques, je suppose que vous avez des connaissances de base sur les structures d'index SQL Server. Voici quelques informations qui vous seront utiles :

  • Une table sans index clusterisé est appelée un tas et n'a pas d'ordre. Il n'y a pas de première ou de dernière rangée. Un tas est juste un groupe de lignes sans ordre particulier.
  • Le niveau feuille d'un index clusterisé est la table elle-même. (Ce n'est pas une copie de la table, c'EST la table.) Les lignes de l'index sont ordonnées logiquement selon la colonne définie comme clé d'index cluster.
  • Le niveau feuille d'un index non cluster contient une ligne d'index pour chaque ligne de la table. Les lignes contiennent les colonnes de clé non clusterisées et sont classées logiquement dans l'ordre dans lequel les clés sont spécifiées. En plus des colonnes clés, les lignes d'index non clusterisées contiennent un « signet » qui pointe vers la ligne référencée dans la table. Le signet peut se présenter sous l'une des deux formes suivantes :
    1. Si la table a un index clusterisé, le signet est la clé de l'index clusterisé. (Si la clé d'index cluster fait partie de la clé d'index non cluster, elle ne sera pas dupliquée.)
    2. Si la table est un tas, le signet est un ID de ligne, ou RID, qui spécifie l'emplacement physique de la ligne. L'emplacement est généralement spécifié sous la forme FileNum:PageNum:RowNum .

Les propres outils de SQL Server offrent plusieurs façons d'afficher le plan d'exécution de requête que l'optimiseur a décidé d'utiliser pour une requête particulière. Avec l'ajout du Quest Spotlight Tuning Pack, vous pouvez obtenir encore plus d'informations sur vos projets.

Le code suivant crée des copies de deux tables dans AdventureWorks base de données (j'utilise AdventureWorks2016 , mais vous pouvez utiliser une autre version).

USE AdventureWorks2016;

GO

DROP TABLE IF EXISTS SalesHeader;

GO

SELECT *

INTO SalesHeader

FROM Sales.SalesOrderHeader;

GO

DROP TABLE IF EXISTS SalesDetail;

GO

SELECT * INTO SalesDetail

FROM Sales.SalesOrderDetail;

GO

Exécutez maintenant une requête qui joint les deux tables ensemble, après avoir activé "Inclure le plan d'exécution réel"

SELECT h.SalesOrderID, OrderDate, ProductID, UnitPrice, OrderQty

FROM SalesHeader h JOIN SalesDetail d

ON h.SalesOrderID = d.SalesOrderID

WHERE SalesOrderDetailID < 100;

GO

Quest Spotlight Tuning Pack signalera un problème avec la requête, vous pouvez donc cliquer sur "Afficher l'analyse" et choisir l'option "Plan d'exécution". Vous devriez voir ce qui suit :

Comprendre les analyses de table

Tout d'abord, je veux prendre des risques et dire qu'il n'y a pas de plan opérateur qui soit toujours mauvais ! Pourquoi l'optimiseur l'ajouterait-il à votre plan de requête s'il était mauvais ? Cela peut indiquer qu'il y a place à l'amélioration de vos structures de données ou d'index, mais en soi, ce n'est pas mauvais.

Dans l'exemple ci-dessus, le Tuning Pack semble mettre en lumière les analyses de table, indiquant qu'elles peuvent être problématiques. Mais il n'est pas toujours vrai que les balayages de table sont problématiques. Une situation bien pire serait d'utiliser une recherche d'index non clusterisée pour une requête qui accède à chaque ligne de la table. Pour cette requête particulière, je conviens que l'analyse n'est peut-être pas une bonne chose car nous ne sommes intéressés que par quelques lignes dans le SalesDetail tableau (99 lignes sur 121 317, soit moins d'un dixième de pour cent.)

Nous pourrions donc examiner les suggestions du volet Analyse pour créer des index. La suggestion pour le SalesDetail table est de construire un index non clusterisé sur le SalesOrderID colonne (la colonne de la clause JOIN) et INCLUDE toutes les autres colonnes de la table renvoyées par la requête. La suggestion pour le SalesHeader table est un index non clusterisé sur SalesOrderDetailId colonne, qui est la colonne dans la clause WHERE, et INCLURE la OrderDate colonne, qui est la seule autre colonne renvoyée par cette table.

Et si notre requête était légèrement différente ? Et si j'avais exécuté cette requête en utilisant SELECT * au lieu d'une liste de colonnes spécifique. Si vous l'essayez et regardez les recommandations, il suggère d'utiliser INCLUDE pour chaque colonne de la table autre que la colonne de clé unique. Bien qu'un tel index puisse accélérer un peu l'exécution de cette requête particulière, il pourrait finir par ralentir d'autres requêtes, en particulier vos requêtes UPDATE. Cet index n'est en fait qu'une copie de la table, car le niveau feuille de l'index contiendra chaque colonne de la table. Si vous voyez des recommandations comme celle-ci suggérant un index qui inclut toutes les colonnes du tableau, je vous recommande vivement de prendre un peu de recul et de ne pas le créer aveuglément.

L'optimisation des requêtes pour les diagnostics de votre serveur SQL implique non seulement la gestion des index, mais également la gestion des requêtes elles-mêmes. Pour cette requête particulière, nous ferions peut-être mieux de réécrire la requête pour NE PAS utiliser le SELECT * pour renvoyer chaque ligne de la table. Renvoyez seulement un petit sous-ensemble des colonnes pourrait être suffisant, et alors un index beaucoup plus étroit suffirait, comme dans le premier exemple.

L'un ou l'autre de ces index serait-il réellement un bon index à créer ? L'index plus étroit sera globalement plus petit et sera moins impacté par les mises à jour des données. Un index sur toutes les colonnes est comme une seconde copie de la table, triée dans un ordre différent de celui de la table elle-même. Il y a des situations où avoir une "deuxième copie" de la table dans un ordre différent peut être utile, mais il y aura beaucoup de frais généraux pour les opérations de modification des données. La seule façon de le savoir avec certitude est d'essayer les recommandations sur un système de test avec une charge de travail représentative. Vous seul connaissez vos données et vos requêtes, alors essayez-le et voyez !

Comprendre les analyses d'index

Comme je l'ai mentionné ci-dessus, les analyses de table ne sont pas toujours une mauvaise chose. Mais qu'en est-il des analyses d'index ? Étant donné qu'un niveau feuille d'index clusterisé est la table elle-même, un parcours d'index clusterisé est identique à un parcours de table ! si un parcours de table est mauvais, un parcours d'index clusterisé est tout aussi mauvais. Mais ce n'est pas toujours mauvais. Encore une fois, vous devez le tester sur votre système.

Les recommandations du moteur SQL Server que Quest Spotlight Tuning Pack vous montre ne suggèrent jamais un index clusterisé. il peut suggérer un non-cluster qui inclut chaque colonne de la table (comme mentionné précédemment), qui n'est qu'un doublon de la table. Déterminer la ou les meilleures colonnes pour votre index clusterisé est un sujet important en soi, donc je ne vais pas m'y attarder ici.

Qu'est-ce qu'une recherche ? Une opération de recherche dans un plan signifie que SQL Server utilise les données ordonnées dans l'arborescence d'index pour rechercher une ligne, un ensemble de lignes ou le point de départ et/ou d'arrêt dans une plage de lignes. En général, l'utilisation d'une recherche d'index non clusterisée est une opération parfaitement raisonnable si vous ne renvoyez qu'un très petit pourcentage de lignes d'une table. Mais une recherche n'est pas un bon choix pour une requête qui renvoie BEAUCOUP de lignes d'une table. Combien font LOTS ? Il n'y a pas de réponse simple, mais si votre requête renvoie plus de quelques pour cent des lignes, vous devez vous assurer de tester soigneusement les suggestions d'index. Parfois, un balayage de table ou un balayage d'index clusterisé est préférable à une recherche d'index. (Pour un exemple de ce type, voir mon article de blog ici).

Des outils tels que Quest Spotlight Tuning Pack peut vous donner d'excellentes suggestions pour commencer votre parcours de réglage avec les diagnostics SQL Server, mais plus vous en savez sur le fonctionnement des index SQL Server et de l'optimiseur SQL Server, mieux vous serez en mesure d'évaluer ces suggestions pour vos requêtes et votre données, et peut-être même proposer vos propres suggestions.

Dans les articles suivants de cette série, je vous parlerai d'autres opérateurs problématiques qui pourraient apparaître dans vos plans de requête, alors revenez bientôt !