J'ai joué sur les seuils d'échantillonnage avec des mises à jour de statistiques sur SQL Server (2012) et j'ai remarqué un comportement curieux. Fondamentalement, le nombre de lignes échantillonnées semble varier dans certaines circonstances - même avec le même ensemble de données.
J'exécute cette requête:
--Drop table if exists
IF (OBJECT_ID('dbo.Test')) IS NOT NULL DROP TABLE dbo.Test;
--Create Table for Testing
CREATE TABLE dbo.Test(Id INT IDENTITY(1,1) CONSTRAINT PK_Test PRIMARY KEY CLUSTERED, TextValue VARCHAR(20) NULL);
--Insert enough data so we have more than 8Mb (the threshold at which sampling kicks in)
INSERT INTO dbo.Test(TextValue)
SELECT TOP 1000000 'blahblahblah'
FROM sys.objects a, sys.objects b, sys.objects c, sys.objects d;
--Create Index on TextValue
CREATE INDEX IX_Test_TextValue ON dbo.Test(TextValue);
--Update Statistics without specifying how many rows to sample
UPDATE STATISTICS dbo.Test IX_Test_TextValue;
--View the Statistics
DBCC SHOW_STATISTICS('dbo.Test', IX_Test_TextValue) WITH STAT_HEADER;
Lorsque je regarde la sortie de SHOW_STATISTICS, je constate que les "lignes échantillonnées" varient à chaque exécution complète (c'est-à-dire que la table est supprimée, recréée et repeuplée).
Par exemple:
Lignes échantillonnées
- 318618
- 319240
- 324198
- 314154
Je m'attendais à ce que ce chiffre soit le même à chaque fois que le tableau est identique. Soit dit en passant, je n'obtiens pas ce comportement si je supprime simplement les données et les réinsère.
Ce n'est pas une question critique, mais je serais intéressé à comprendre ce qui se passe.
la source
318618 = 1142*279
,319240 = 1144*279 + 64
,324198=1162*279
Et314154=1126
donc la variance est le nombre de pages de l' échantillon.Réponses:
Contexte
Les données de l'objet statistiques sont collectées à l'aide d'une instruction de la forme:
Vous pouvez collecter cette instruction avec Extended Events ou Profiler (
SP:StmtCompleted
).Les requêtes de génération de statistiques accèdent souvent à la table de base (plutôt qu'à un index non cluster) pour éviter le regroupement de valeurs qui se produit naturellement sur les pages d'index non cluster.
Le nombre de lignes échantillonnées dépend du nombre de pages entières sélectionnées pour l'échantillonnage. Chaque page du tableau est sélectionnée ou ne l'est pas. Toutes les lignes des pages sélectionnées contribuent aux statistiques.
Nombres aléatoires
SQL Server utilise un générateur de nombres aléatoires pour décider si une page est admissible ou non. Le générateur utilisé dans ce cas est le générateur de nombres aléatoires Lehmer avec des valeurs de paramètres comme indiqué ci-dessous:
La valeur de est calculée comme la somme de:
Xseed
La partie entière basse de la
bigint
table de base ( ),partition_id
par exempleLa valeur spécifiée dans la
REPEATABLE
clauseUPDATE STATISTICS
, laREPEATABLE
valeur est 1.m_randomSeed
élément des informations de débogage internes de la méthode d'accès affichées dans les plans d'exécution lorsque l'indicateur de trace 8666 est activé, par exemple<Field FieldName="m_randomSeed" FieldValue="1" />
Pour SQL Server 2012, ce calcul se produit dans
sqlmin!UnOrderPageScanner::StartScan
:où la mémoire à
[rcx+30h]
contient les 32 bits de poids faible de l'ID de partition et la mémoire à[rcx+2Ch]
contient laREPEATABLE
valeur utilisée.Le générateur de nombres aléatoires est initialisé plus tard dans la même méthode, appelant
sqlmin!RandomNumGenerator::Init
, où l'instruction:... multiplie la graine par
41A7
hex (16807 décimal = 7 5 ) comme indiqué dans l'équation ci-dessus.Les nombres aléatoires ultérieurs (pour les pages individuelles) sont générés à l'aide du même code de base intégré à
sqlmin!UnOrderPageScanner::SetupSubScanner
.StatMan
Pour l'exemple de
StatMan
requête ci-dessus, les mêmes pages seront collectées que pour l'instruction T-SQL:Cela correspondra à la sortie de:
Cas de bord
L'une des conséquences de l'utilisation du générateur de nombres aléatoires MINSTD Lehmer est que les valeurs de départ zéro et int.max ne doivent pas être utilisées car cela entraînera la production par l'algorithme d'une séquence de zéros (sélection de chaque page).
Le code détecte zéro et utilise une valeur de l '«horloge» du système comme valeur de départ dans ce cas. Il n'en va pas de même si la valeur de départ est int.max (
0x7FFFFFFF
= 2 31 - 1).Nous pouvons concevoir ce scénario car la graine initiale est calculée comme la somme des 32 bits bas de l'id de partition et de la
REPEATABLE
valeur. LaREPEATABLE
valeur qui se traduira par la graine étant int.max et donc chaque page sélectionnée pour l'échantillon est:En travaillant cela dans un exemple complet:
Cela sélectionnera chaque ligne de chaque page, quelle que soit la
TABLESAMPLE
clause (même zéro pour cent).la source
Ceci est une excellente question! Je vais commencer par ce que je sais avec certitude, puis passer à la spéculation. Beaucoup de détails à ce sujet dans mon article de blog ici .
Des mises à jour de statistiques échantillonnées sont utilisées
TABLESAMPLE
dans les coulisses. Il est assez facile de trouver de la documentation en ligne à ce sujet. Cependant, je pense qu'il n'est pas bien connu que les lignes renvoyées parTABLESAMPLE
dépendent en partiehobt_id
de l'objet. Lorsque vous déposez et recréez l'objet, vous obtenez un nouveauhobt_id
afin que les lignes renvoyées par échantillonnage aléatoire soient différentes.Si vous supprimez et réinsérez les données, elles
hobt_id
restent inchangées. Tant que les données sont disposées de la même manière sur le disque (une analyse de l'ordre d'allocation renvoie les mêmes résultats dans le même ordre), les données échantillonnées ne doivent pas changer.Vous pouvez également modifier le nombre de lignes échantillonnées en reconstruisant l'index cluster sur la table. Par exemple:
Quant à savoir pourquoi cela se produit, je pense que c'est parce que SQL Server analyse l'index clusterisé au lieu de l'index non cluster lors de la collecte des statistiques échantillonnées sur un index. Je pense également qu'il y a une valeur cachée (pour ceux d'entre nous qui tracent les requêtes de mise à jour des statistiques cachées) à
REPEATABLE
utiliser avecTABLESAMPLE
. Je n'ai rien prouvé, mais cela explique pourquoi votre histogramme et les lignes échantillonnées changent avec une reconstruction de l'index clusterisé.la source
J'ai vu cela dans Inside Microsoft SQL Server 2008: Requête T-SQL par Itzik Ben-Gan et je ne peux pas l'ajouter en tant que commentaire, donc je le poste ici, je pense que c'est intéressant pour les autres aussi:
Voir aussi Sampling Using TABLESAMPLE by Roji. P. Thomas.
la source