Existe-t-il un moyen de déterminer si les requêtes SQL Server s'exécutent en mémoire ou vont sur le disque?

13

Je suis tombé sur un ensemble de procédures stockées dans une application aujourd'hui qui sont appelées à plusieurs reprises au cours d'un long processus. Dans chaque procédure, j'ai trouvé plusieurs instructions select différentes, certaines dans des boucles; sans surprise, ces routines telles qu'elles sont actuellement utilisées prennent plusieurs minutes à s'exécuter, alors que l'intuition s'attend à ce qu'elles se terminent en quelques secondes.

Il semble assez évident que les performances n'ont pas été prises en compte lors de la rédaction de ces procédures, il y a plusieurs exemples de choses qui ne sont "pas une bonne idée".

Le traitement de chaque ligne lors de l'importation de données prend 300 ms par ligne, de sorte que les importations relativement petites prennent plusieurs minutes à traiter.

Cependant, les tableaux impliqués dans les procédures sont pour la plupart assez petits. Je pense que si toutes ces tables résident entièrement dans la mémoire, il n'y a peut-être pas grand-chose à gagner en réécrivant tout cela.

J'essaie de déterminer .... pour ce code manifestement inefficace, quel effet réel a-t-il? Vaut-il la peine d'être réparé?

La question est donc:
- existe-t-il un moyen de déterminer quelles tables sont entièrement épinglées en mémoire?
- existe-t-il un moyen d'activer le traçage afin de surveiller les procédures stockées imbriquées pour trouver les portions particulièrement coûteuses?

Remarque: c'est sur SQL Server 2008 R2

tbone
la source

Réponses:

12

Vous pouvez utiliser l'une de ces deux requêtes pour voir le total des lectures logiques et le total des lectures physiques.

SELECT  DB_NAME(st.dbid) Db,
        OBJECT_NAME(st.objectid, st.dbid) Prc,
        qs.execution_count,
        qs.total_logical_reads,
        qs.total_physical_reads,
        qs.statement_start_offset,
        qs.statement_end_offset,
        st.text
FROM    sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st;

SELECT  DB_NAME(database_id) Db,
        OBJECT_NAME(object_id, database_id) Prc,
        execution_count,
        total_logical_reads,
        total_physical_reads
FROM    sys.dm_exec_procedure_stats ps;

Le premier décompose cela par instruction, le second compte dans toute la procédure.

Les lectures physiques sont des lectures sur le disque, les lectures logiques sont sur la mémoire. Vous pouvez l'utiliser pour déterminer quelles procédures ou instructions sont les plus coûteuses de votre système et essayer de les régler.

Gardez à l'esprit que, bien que les lectures logiques soient nettement moins chères que les lectures physiques, elles sont toujours coûteuses, donc en réduire le nombre (par exemple en ajoutant un index approprié) peut accélérer l'exécution de vos requêtes.

Il y a beaucoup de colonnes supplémentaires dans les DMV ci-dessus qui pourraient également vous intéresser.


Comment un index aide-t-il à réduire les lectures logiques?

Dans SQL Server, toutes les données sont organisées en blocs, d'une taille de 8 Ko. Ces blocs sont appelés "pages".

Chaque table contient des pages "meta" qui contiennent des informations sur le struktur de la table ainsi que des pages pata. Si aucun index n'existe et que vous exécutez une requête comme SELECT * FROM tbl WHERE Id = 7SQL Server, vous devez rechercher ceci ou ces lignes dans la table entière. Il lit donc une page à la fois, parcourt toutes les lignes de chaque page pour déterminer les lignes qui correspondent à la WHEREclause. Donc, si la table nécessite 1 000 000 de pages à stocker, cette requête nécessitera 1 000 000 de lectures logiques.

Si vous avez un index, SQL Server trie les données de manière logique dans les pages et établit une liste liée entre les pages. Cela permet d'exécuter des requêtes avec un ORDER BYà exécuter sans opération de tri coûteuse. Mais plus important encore que le tri, SQL Server ajoute un arbre B + à la table. Un arbre B + est une structure comparable à l'index d'un livre, où la recherche d'un mot clé spécifique me permet de passer directement à la page qui contient le mot clé. Le livre typique n'a qu'un seul niveau d'index alors qu'un arbre B + peut en avoir plusieurs. Pensez simplement à un grand livre, où l'index lui-même fait plusieurs pages. Dans un cas comme celui-ci, il est logique d'ajouter une couche d'index supplémentaire qui nous indique sur quelle page les mots d'index commençant par Sdoivent être trouvés.

Les arbres B + sont optimisés pour avoir le moins de niveaux possible tout en offrant la propriété que tout enregistrement dans l'index peut être trouvé en lisant une page par niveau d'index. Supposez donc la WHERE Id = 7requête ci-dessus lorsque vous avez un index trié par Id. Disons que l'indice a 5 niveaux. Maintenant, pour trouver tous les enregistrements qui correspondent à cette requête, je dois lire une page par niveau d'index (c'est-à-dire 5 pages). Cela s'appelle une "recherche d'index". S'il y a plusieurs enregistrements qui correspondent à la facture, je devrai peut-être suivre l'index trié pendant un certain temps pour les récupérer tous. Mais supposons qu'il n'y ait qu'un seul enregistrement.

Ainsi, sans l'index en cours d'exécution, cette requête a nécessité 1 000 000 de lectures, avec indes, elle a nécessité 5 lectures. Même si une lecture logique est une opération en mémoire, il y a toujours un coût substantiel - en fait, c'est l'opération la plus coûteuse dans une requête triviale comme celle ci-dessus. Ainsi, la réduction du nombre de lectures logiques nécessaires d'un facteur 200 000 accélérera votre requête d'un facteur similaire.

Ainsi, une lecture logique n'est pas équivalente à une analyse de table, mais une analyse de table provoque beaucoup plus de lectures logiques qu'une recherche d'index.

Sebastian Meine
la source
> "... en réduire le nombre (par exemple en ajoutant un index approprié) peut accélérer l'exécution de vos requêtes." Pourriez-vous expliquer comment l'ajout d'un index réduira (?) Les lectures logiques? La lecture logique est-elle synonyme d'une analyse de table?
1
Ajout d'une explication à ma réponse ci-dessus.
Sebastian Meine
Merci. Même en supposant que les index appropriés se trouvent sur toutes les tables impliquées ... Je pense qu'il y a encore une grande différence de performances entre une table épinglée en mémoire et lue sur le disque (supposez les mêmes index dans les deux scénarios) ... ou dans d'autres En d'autres termes, l'ajout d'index vous permettra d'obtenir un% de performances en moins sur une machine avec beaucoup de RAM que sur une machine avec moins de mémoire ... correct?
1
L'accès au disque physique est clairement de l'ordre de grandeur plus cher que l'accès à la mémoire. Donc, prendre des mesures pour l'éviter vous mènera très loin. Vous devez toujours regarder le nombre de lectures logiques en premier lors du réglage de la requête. Les maintenir faibles maintiendra à son tour des lectures physiques faibles. Il est également fort probable que les pages ne doivent pas être supprimées du cache, ce qui réduit encore plus les lectures physiques requises.
Sebastian Meine
2
Petite piqûre - je pense que les pages font 8kb :-). Bonne réponse.
onupdatecascade
3
  • existe-t-il un moyen d'activer le traçage afin de surveiller les procédures stockées imbriquées pour trouver les portions particulièrement coûteuses?

Vous pouvez utiliser SQL Profiler. Lorsque vous démarrez la trace, vous devez choisir RPC Completed, SP Starting, SP StmtStarting et SP StmtCompleted (voir l'image ci-dessous)

entrez la description de l'image ici

Cela vous permettra de voir chaque requête qui s'exécute à l'intérieur des procédures stockées. Il vous permettra de voir combien de fois une procédure stockée imbriquée est appelée. Une fois la trace terminée, vous devez l'enregistrer. Ensuite, rouvrez-le, et après cela, vous pourrez filtrer (avec le bouton "Filtres de colonne") pour trouver les requêtes qui vous posent problème. (ex: les requêtes qui ont pris plus de x lectures ou qui ont duré plus de x secondes (durée) ...)

Les options du profileur que je vous ai montrées montrent également le plan d'exécution, ce qui est également très utile.

Danielle Paquette-Harvey
la source
1

Cela semble être une question générale d'optimisation des requêtes. D'après votre description, je voudrais:

  1. Examinez le code pour voir s'il effectue un traitement ligne par ligne. Si c'est le cas, il est souvent possible d'améliorer l'ordre de grandeur en implémentant la même logique à l'aide d'ensembles (plusieurs lignes traitées en même temps). En d'autres termes, s'il agit comme une "boucle sur chaque ligne", remplacez-le par "traiter toutes les lignes". SQL excelle dans ce domaine, car l'optimiseur peut choisir parmi plusieurs méthodes possibles, potentiellement utiliser le parallélisme, supprimer un grand nombre de frais généraux provenant d'une ligne à la fois.
  2. Assurez-vous ensuite qu'il existe des index qui prennent en charge le travail. Souvent, encore une fois, des ordres de grandeur peuvent être obtenus avec des indices corrects ou non. Cela est vrai en mémoire et avec accès au disque. Les processus peuvent toujours prendre des heures avec tout dans la RAM s'il n'y a pas d'index appropriés sur un grand ensemble de données.
  3. Ensuite, avec la logique définie et les index en place, j'examinerais si les pages de données affectées tiennent en mémoire. À ce stade, s'il y a encore beaucoup d'accès au disque, il est logique d'examiner les lectures physiques et l'activité du disque, car tous les gros gains de l'optimisation sont réalisés au cours des deux premières étapes.
onupdatecascade
la source