Conseils d'optimisation des requêtes SQL Server 2005/8

13

Je cherche à éduquer une équipe sur la rédaction de meilleures requêtes SQL Server et je me demandais quels étaient les meilleurs conseils des gens pour améliorer les performances.

Par exemple, j'ai eu un DBA qui insistait sur le fait que count (*) fonctionnerait moins bien que count (1) (je ne sais pas si elle avait raison ou si elle est toujours valide par rapport aux derniers optimiseurs de requête).

Quelles choses simples devrais-je dire à l'équipe d'essayer de toujours utiliser ou d'éviter? Je recherche idéalement des choses qui (a) pourraient faire une différence raisonnable et (b) sont simples, 1 à 2 lignes à énoncer.

Jon Hopkins
la source

Réponses:

13

Réglage des requêtes 101

Il n'y a pas de solution miracle pour interroger le réglage, bien que je puisse vous donner quelques conseils et astuces. La première chose à faire est de comprendre ce qui se passe réellement dans les coulisses. Obtenez un bon livre sur les internes comme le troisième guide du gourou.

Les requêtes peu performantes ont tendance à se présenter sous deux formes fondamentales: les requêtes transactionnelles qui prennent trop de temps et les tâches de traitement par lots (ou rapports) qui prennent trop de temps. Un bon signe d'une requête avec quelque chose qui ne va pas est un élément unique dans le plan de requête prenant 99% du temps.

Requêtes transactionnelles

Dans la plupart des cas, une requête transactionnelle peu performante est l'une des choses suivantes:

  • Un index manquant. Vous pouvez le voir dans le plan de requête - des analyses de table de grandes tables sur une jointure qui devraient être très sélectives (c'est-à-dire retourner quelques lignes).

  • Requête incapable d'utiliser un index. Si vous avez des conditions OU dans la clause where, des jointures sur une valeur calculée ou un autre élément de la requête qui n'est pas sarg-able, vous devrez peut-être réécrire la requête. En bref, les sargs sont des prédicats de requête qui peuvent utiliser des index pour éliminer les lignes. ET logique, égalité et inégalité (>,> =, <, <= et! =) Sont toutes acceptables. OU n'est traditionnellement pas sarg-capable. Cependant, vous pouvez souvent traduire les OR en prédicats pouvant être limités en inversant le sens de OR vers les constructions de type NOT (foo et not bar).

  • Prédicats inefficaces. Par exemple, si vous avez where inréférençant une sous-requête imbriquée, voyez si elle peut être réécrite en tant que where existsou en tant que jointure. Cela peut entraîner des plans de requête plus efficaces et voici d'autres réécritures standard que vous pouvez également essayer. Encore une fois, les guides du Guru et d'autres sur le sujet sont un bon point de départ.

Requêtes par lots

Les requêtes par lots sont plus compliquées et présentent différents problèmes de réglage. Quelques conseils:

  • Indexage. Cela peut faire une grande différence pour la même raison que pour les requêtes transactionnelles. Souvent, un bon signe d'un index manquant est une longue opération de meulage (99% du plan de requête) qui ne semble pas écraser la machine.

  • Tables temporaires. Il peut être préférable de décomposer une requête en plusieurs requêtes remplissant des tables temporaires. Les requêtes plus volumineuses donnent à l'optimiseur plus de marge de manœuvre, bien que ce soit moins un problème qu'auparavant. Créez les tables temporaires avec select intocar cette opération est journalisée de manière minimale (beaucoup moins d'activité de journal), ce qui réduit la charge d'E / S.

    Notez que les tables temporaires dans tempdb sont la même structure de données que l'optimiseur utilise pour stocker les résultats de jointure intermédiaires, il n'y a donc aucune pénalité de performance pour cela. Vous pouvez également créer un index (y compris les index cluster et couvrant) sur une table temporaire, ce qui peut améliorer les performances des requêtes qui le lisent pour les mêmes raisons qu'elles améliorent les requêtes sur les tables statiques.

    N'exagérez pas les tables temporaires, car elles peuvent rendre les choses plus difficiles à retracer dans la requête. Pour les petites tables dans une procédure stockée, testez pour voir si les variables de table vous aident. Il s'agit d'une structure de données en mémoire, elles peuvent donc être un gain de performances.

  • Index groupés et couvrant. Ceux-ci peuvent améliorer les performances d'une requête car ils forcent la localité de référence sur le disque en fonction d'une colonne de regroupement. Un index clusterisé peut faire une grande différence dans les performances d'un travail par lots.

  • Prédicats inefficaces. Celles-ci peuvent provoquer des problèmes avec les sargs et autres émissions de sous-optimisation de la même manière qu'avec les requêtes transactionnelles.

  • Le scan de table est votre ami. Contrairement à la croyance populaire, les scans de table ne sont pas intrinsèquement mauvais. En général, ils sont le signe d'un problème dans une requête transactionnelle, mais ils sont souvent le moyen le plus efficace d'effectuer une opération par lots volumineuse. Si vous faites quelque chose avec plus de quelques pour cent de lignes dans une table, une analyse de table est souvent le moyen le plus efficace de couvrir la table.

  • Jointures de boucles imbriquées. Jetez un œil à ce que fait l'optimiseur des deux côtés de la jointure. Celles-ci peuvent être inefficaces si vous l'êtes (par exemple, une table analysant deux grandes tables des deux côtés d'une jointure de boucles imbriquées. Pensez à utiliser des index clusterisés order byet à essayer de changer l'opération en jointure de fusion ou à suggérer de promouvoir une jointure de hachage si un côté est assez petit pour le faire.

Verrouillage

Le verrouillage peut également entraîner des problèmes de performances. Si votre système fonctionne mal sous charge, examinez le profileur et les compteurs perfmon liés aux verrous et vérifiez s'il existe des conflits importants. sp_who2a une colonne 'BlkBy' dans le jeu de résultats qui montrera si une requête est bloquée et ce qui la bloque. En outre, les profils avec des événements de «graphique de blocage» (si vous avez des requêtes de blocage) et des événements liés au verrouillage peuvent être utiles pour résoudre les problèmes de verrouillage.

ConcernedOfTunbridgeWells
la source
1
+1 car c'est une excellente information sur le réglage des performances (j'ai eu le plaisir d'être dans les classes de Kalen. Elle sait de quoi elle parle!). Vous pouvez simplement ajouter des informations sur les vues dynamiques.
Wayne
3

Meilleur conseil: utilisez SQL Server 2008 et exécutez le moniteur d'activité pendant l'exécution de vos tests. Notez les requêtes qui prennent le plus de temps / qui ont le plus d'E / S, etc. Cliquez avec le bouton droit sur ces requêtes pour afficher la requête et / ou le plan d'exécution.

Ensuite: apprenez à comprendre les plans d'exécution.

Suivant: Utilisez l'assistant de réglage de la base de données.

Ces étapes vous aideront à générer vos propres «meilleurs conseils».

John Saunders
la source
2

Un excellent ebook gratuit de RedGate sur la façon de travailler avec et de comprendre les plans d'exécution de SQL Server

http://www.red-gate.com/specials/Grant.htm?utm_content=Grant080623

Shameless Plug, je référence les matériaux d'optimisation des performances sur mon blog sous SQL Server Performance .

Une fois que vous avez eu l'occasion de digérer une partie de ce matériel, n'hésitez pas à poster ici ou à me contacter directement pour des questions spécifiques.

John Sansom
la source
1

Tout d'abord, l'indexation. Beaucoup de gens ne réalisent pas que les clés étrangères n'obtiennent pas automatiquement les index. Puisqu'ils sont utilisés dans des jointures, ils devraient presque toujours avoir un index.

Examinez attentivement tous les curseurs pour voir s'ils peuvent être remplacés par du code basé sur un ensemble. J'ai changé le code qui a fonctionné pendant des heures en secondes en faisant cela.

Évitez les sous-requêtes. Si vous les avez dans le code, remplacez-les par des jointures ou des jointures à des tables dérivées.

Assurez-vous que votre clause where est négociable.

Apprenez à lire les plans d'exécution.

Assurez-vous que le bureau a quelques bons livres sur le réglage des performances.

Les variables de table sont meilleures que les tables temporaires dans certains cas et les tables temporaires fonctionnent mieux dans d'autres. Si vous devez les utiliser, essayez les deux et voyez celle qui fonctionne mieux dans ce cas particulier.

HLGEM
la source