web-dev-qa-db-fra.com

Comment les rangées dans le profileur SQL Server sont-elles calculées?

J'ai un problème où les comptes retournés par la colonne RowCounts dans un SP:StmtCompleted Sont différentes des lignes réelles retournées pour l'exécution d'une instruction SELECT.

J'ai essayé un select @@RowCount Après la requête SELECT et renvoie les mêmes comptes que count(*). Je suis curieux maintenant ce qui pourrait causer que le profileur retourne des chiffres de ligne incorrects.

J'ai lu des threads liés à suggérer une fragmentation peut générer de mauvais compte et un DBCC UPDATEUSAGE Pourrait résoudre le problème, mais je veux comprendre ce que je fais avant de l'appliquer. J'apprécierais une certaine élaboration. De plus, les index jouent-ils un rôle dans les comptes?

Q & A associé: SQL Server Row Row comptage SP_SPACACEUSÉ Disque divergence

J'utilise le profileur SQL Server 2014.

C'est ainsi que vous pouvez voir les numérons de ligne dans le profileur, au cas où l'on se demande: Afficher le compte de ligne dans le profileur SQL

3
D.S.

Généralement, vous pouvez vous attendre à ce que le nombre de lignes signalé correspondra au nombre de lignes renvoyées à l'appelant (et au (x row(s) affected) Message dans SQL Server Management Studio dans le cas d'une requête de niveau supérieur).

Toutefois, lorsque la déclaration contient des appels imbriqués, tels que une fonction scalaire définie par l'utilisateur, les numérations de lignes générées dans les appels (répétés) au plan d'exécution de la fonction seront ajoutés au total. Ceci est un effet secondaire malheureux de l'endroit où le comptage est effectué * et la manière dont les fonctions non lignes sont actuellement mises en œuvre. il a été considéré comme suffisamment important pour corriger .

Dans l'exemple de point de connexion lié (mieux formaté dans le parent blog post par gars Glanster), le nombre total de lignes pour la requête qui renvoie 100 rangées est signalé comme 300, en raison de la seule ligne affectée par chaque des deux déclarations de la fonction, sur chaque invocation.

Si la fonction est réduite à une seule déclaration:

RETURN CAST(@DateTimeValue AS date);

... Le nombre est de 200 (100 rangées pour la requête extérieure, plus 1 rangée cent fois pour la fonction).

DBCC UPDATEUSAGE n'auguera pas cela. Les index et la fragmentation n'ont aucune roulement non plus. C'est simplement une conséquence architecturale et une autre raison d'éviter les fonctions non lignes.


* Les détails sont plutôt ésotériques. Grandes, pour une requête SELECT, c'est le nombre de lignes vues au nœud racine du plan. Il existe une structure de mémoire partagée impliquée et rien que vous puissiez voir directement dans un plan d'exécution. Lorsqu'une fonction scalaire est exécutée, elle le fait dans un sous-compteur qui arrive à partager la structure. Peut-être que ceci est par conception, il est difficile de savoir avec certitude sans accès de code source. Mon sentiment (comme indiqué) est qu'il s'agit d'un effet secondaire inattendu. Pour les requêtes DML, un nœud de plan particulier est attribué au travail de maintien du nombre de lignes . Cela peut différer de manière significative en fonction de la forme du plan (par exemple si une clause OUTPUT est utilisée ou le traitement de la mise à jour de l'effondrement par fraction est utilisé).

6
Paul White 9