Comment le nombre d'étapes de l'histogramme est-il décidé dans Statistics

11

Comment le nombre d'étapes de l'histogramme est-il décidé dans Statistiques dans SQL Server?

Pourquoi est-il limité à 200 étapes même si ma colonne de clé a plus de 200 valeurs distinctes? Y a-t-il un facteur décisif?


Démo

Définition du schéma

CREATE TABLE histogram_step
  (
     id   INT IDENTITY(1, 1),
     name VARCHAR(50),
     CONSTRAINT pk_histogram_step PRIMARY KEY (id)
  )

Insérer 100 enregistrements dans ma table

INSERT INTO histogram_step
            (name)
SELECT TOP 100 name
FROM   sys.syscolumns

Mise à jour et vérification des statistiques

UPDATE STATISTICS histogram_step WITH fullscan

DBCC show_statistics('histogram_step', pk_histogram_step)

Étapes de l'histogramme:

+--------------+------------+---------+---------------------+----------------+
| RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | AVG_RANGE_ROWS |
+--------------+------------+---------+---------------------+----------------+
|            1 |          0 |       1 |                   0 |              1 |
|            3 |          1 |       1 |                   1 |              1 |
|            5 |          1 |       1 |                   1 |              1 |
|            7 |          1 |       1 |                   1 |              1 |
|            9 |          1 |       1 |                   1 |              1 |
|           11 |          1 |       1 |                   1 |              1 |
|           13 |          1 |       1 |                   1 |              1 |
|           15 |          1 |       1 |                   1 |              1 |
|           17 |          1 |       1 |                   1 |              1 |
|           19 |          1 |       1 |                   1 |              1 |
|           21 |          1 |       1 |                   1 |              1 |
|           23 |          1 |       1 |                   1 |              1 |
|           25 |          1 |       1 |                   1 |              1 |
|           27 |          1 |       1 |                   1 |              1 |
|           29 |          1 |       1 |                   1 |              1 |
|           31 |          1 |       1 |                   1 |              1 |
|           33 |          1 |       1 |                   1 |              1 |
|           35 |          1 |       1 |                   1 |              1 |
|           37 |          1 |       1 |                   1 |              1 |
|           39 |          1 |       1 |                   1 |              1 |
|           41 |          1 |       1 |                   1 |              1 |
|           43 |          1 |       1 |                   1 |              1 |
|           45 |          1 |       1 |                   1 |              1 |
|           47 |          1 |       1 |                   1 |              1 |
|           49 |          1 |       1 |                   1 |              1 |
|           51 |          1 |       1 |                   1 |              1 |
|           53 |          1 |       1 |                   1 |              1 |
|           55 |          1 |       1 |                   1 |              1 |
|           57 |          1 |       1 |                   1 |              1 |
|           59 |          1 |       1 |                   1 |              1 |
|           61 |          1 |       1 |                   1 |              1 |
|           63 |          1 |       1 |                   1 |              1 |
|           65 |          1 |       1 |                   1 |              1 |
|           67 |          1 |       1 |                   1 |              1 |
|           69 |          1 |       1 |                   1 |              1 |
|           71 |          1 |       1 |                   1 |              1 |
|           73 |          1 |       1 |                   1 |              1 |
|           75 |          1 |       1 |                   1 |              1 |
|           77 |          1 |       1 |                   1 |              1 |
|           79 |          1 |       1 |                   1 |              1 |
|           81 |          1 |       1 |                   1 |              1 |
|           83 |          1 |       1 |                   1 |              1 |
|           85 |          1 |       1 |                   1 |              1 |
|           87 |          1 |       1 |                   1 |              1 |
|           89 |          1 |       1 |                   1 |              1 |
|           91 |          1 |       1 |                   1 |              1 |
|           93 |          1 |       1 |                   1 |              1 |
|           95 |          1 |       1 |                   1 |              1 |
|           97 |          1 |       1 |                   1 |              1 |
|           99 |          1 |       1 |                   1 |              1 |
|          100 |          0 |       1 |                   0 |              1 |
+--------------+------------+---------+---------------------+----------------+

Comme nous pouvons le voir, l'histogramme comporte 53 étapes.

Insérant à nouveau quelques milliers d'enregistrements

INSERT INTO histogram_step
            (name)
SELECT TOP 10000 b.name
FROM   sys.syscolumns a
       CROSS JOIN sys.syscolumns b

Mise à jour et vérification des statistiques

UPDATE STATISTICS histogram_step WITH fullscan

DBCC show_statistics('histogram_step', pk_histogram_step)

Maintenant, les étapes de l'histogramme sont réduites à 4 étapes

+--------------+------------+---------+---------------------+----------------+
| RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | AVG_RANGE_ROWS |
+--------------+------------+---------+---------------------+----------------+
|            1 |          0 |       1 |                   0 |              1 |
|        10088 |      10086 |       1 |               10086 |              1 |
|        10099 |         10 |       1 |                  10 |              1 |
|        10100 |          0 |       1 |                   0 |              1 |
+--------------+------------+---------+---------------------+----------------+

Insérant à nouveau quelques milliers d'enregistrements

INSERT INTO histogram_step
            (name)
SELECT TOP 100000 b.name
FROM   sys.syscolumns a
       CROSS JOIN sys.syscolumns b

Mise à jour et vérification des statistiques

UPDATE STATISTICS histogram_step WITH fullscan

DBCC show_statistics('histogram_step', pk_histogram_step) 

Maintenant, les étapes de l'histogramme sont réduites à 3 étapes

+--------------+------------+---------+---------------------+----------------+
| RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | AVG_RANGE_ROWS |
+--------------+------------+---------+---------------------+----------------+
|            1 |          0 |       1 |                   0 |              1 |
|       110099 |     110097 |       1 |              110097 |              1 |
|       110100 |          0 |       1 |                   0 |              1 |
+--------------+------------+---------+---------------------+----------------+

Quelqu'un peut-il me dire comment ces étapes sont décidées?

P ரதீப்
la source
3
200 était un choix arbitraire. Cela n'a rien à voir avec le nombre de valeurs distinctes que vous avez dans une table spécifique. Si vous voulez savoir pourquoi 200 a été choisi, vous devrez demander à un ingénieur de l'équipe SQL Server des années 90, pas à vos pairs
Aaron Bertrand
1
@AaronBertrand - Merci .. Alors, comment ce nombre d'étapes est-il décidé
P ரதீப்
1
Il n'y a pas de décision. La limite supérieure est 200. Point. Eh bien, techniquement, c'est 201, mais c'est une histoire pour un autre jour.
Aaron Bertrand
1
J'ai posé une question similaire à propos des estimations intrastep, pourrait être utile dba.stackexchange.com/questions/148523/…
jesijesi

Réponses:

14

Je vais limiter ce post à la discussion des statistiques sur une seule colonne, car elles seront déjà assez longues et vous souhaitez savoir comment SQL Server classe les données en étapes d'histogramme. Pour les statistiques multi-colonnes, l'histogramme n'est créé que sur la première colonne.

Lorsque SQL Server détermine qu'une mise à jour des statistiques est nécessaire, il lance une requête masquée qui lit toutes les données d'une table ou un échantillon des données de la table. Vous pouvez afficher ces requêtes avec des événements étendus. Il existe une fonction appelée StatMandans SQL Server qui est impliquée dans la création des histogrammes. Pour les objets statistiques simples, il existe au moins deux types de StatManrequêtes différents (il existe différentes requêtes pour les mises à jour rapides des statistiques et je soupçonne que la fonctionnalité de statistiques incrémentielles sur les tables partitionnées utilise également une requête différente).

Le premier saisit simplement toutes les données de la table sans aucun filtrage. Vous pouvez le voir lorsque le tableau est très petit ou que vous collectez des statistiques avec l' FULLSCANoption:

CREATE TABLE X_SHOW_ME_STATMAN (N INT);
CREATE STATISTICS X_STAT_X_SHOW_ME_STATMAN ON X_SHOW_ME_STATMAN (N);

-- after gathering stats with 1 row in table
SELECT StatMan([SC0]) FROM
(
    SELECT TOP 100 PERCENT [N] AS [SC0] 
    FROM [dbo].[X_SHOW_ME_STATMAN] WITH (READUNCOMMITTED)
    ORDER BY [SC0] 
) AS _MS_UPDSTATS_TBL 
OPTION (MAXDOP 16);

SQL Server choisit la taille d'échantillon automatique en fonction de la taille de la table (je pense que c'est à la fois le nombre de lignes et de pages dans la table). Si un tableau est trop grand, la taille d'échantillon automatique tombe en dessous de 100%. Voici ce que j'ai obtenu pour le même tableau avec 1M de lignes:

-- after gathering stats with 1 M rows in table
SELECT StatMan([SC0], [SB0000]) FROM 
(
    SELECT TOP 100 PERCENT [SC0], step_direction([SC0]) over (order by NULL) AS [SB0000] 
    FROM 
    (
        SELECT [N] AS [SC0] 
        FROM [dbo].[X_SHOW_ME_STATMAN] TABLESAMPLE SYSTEM (6.666667e+001 PERCENT) WITH (READUNCOMMITTED) 
    ) AS _MS_UPDSTATS_TBL_HELPER 
    ORDER BY [SC0], [SB0000] 
) AS _MS_UPDSTATS_TBL
OPTION (MAXDOP 1);

TABLESAMPLEest documenté mais StatMan et step_direction ne le sont pas. ici, SQL Server échantillonne environ 66,6% des données de la table pour créer l'histogramme. Cela signifie que vous pouvez obtenir un nombre différent d'étapes d'histogramme lors de la mise à jour des statistiques (sans FULLSCAN) sur les mêmes données. Je n'ai jamais observé cela dans la pratique mais je ne vois pas pourquoi ce ne serait pas possible.

Exécutons quelques tests sur des données simples pour voir comment les statistiques changent au fil du temps. Vous trouverez ci-dessous un code de test que j'ai écrit pour insérer des entiers séquentiels dans une table, rassembler des statistiques après chaque insertion et enregistrer des informations sur les statistiques dans une table de résultats. Commençons par insérer simplement 1 ligne à la fois jusqu'à 10000. Banc d'essai:

DECLARE
@stats_id INT,
@table_object_id INT,
@rows_per_loop INT = 1,
@num_of_loops INT = 10000,
@loop_num INT;

BEGIN
    SET NOCOUNT ON;

    TRUNCATE TABLE X_STATS_RESULTS;

    SET @table_object_id = OBJECT_ID ('X_SEQ_NUM');
    SELECT @stats_id = stats_id FROM sys.stats
    WHERE OBJECT_ID = @table_object_id
    AND name = 'X_STATS_SEQ_INT_FULL';

    SET @loop_num = 0;
    WHILE @loop_num < @num_of_loops
    BEGIN
        SET @loop_num = @loop_num + 1;

        INSERT INTO X_SEQ_NUM WITH (TABLOCK)
        SELECT @rows_per_loop * (@loop_num - 1) + N FROM dbo.GetNums(@rows_per_loop);

        UPDATE STATISTICS X_SEQ_NUM X_STATS_SEQ_INT_FULL WITH FULLSCAN; -- can comment out FULLSCAN as needed

        INSERT INTO X_STATS_RESULTS WITH (TABLOCK)
        SELECT 'X_STATS_SEQ_INT_FULL', @rows_per_loop * @loop_num, rows_sampled, steps 
        FROM sys.dm_db_stats_properties(@table_object_id, @stats_id);
        END;
END;

Pour ces données, le nombre d'étapes de l'histogramme augmente rapidement à 200 (il atteint d'abord le nombre maximal d'étapes avec 397 lignes), reste à 199 ou 200 jusqu'à ce que 1485 lignes soient dans le tableau, puis diminue lentement jusqu'à ce que l'histogramme n'ait que 3 ou 4 pas. Voici un graphique de toutes les données:

premier graphique

Voici l'histogramme ressemble à 10k lignes:

RANGE_HI_KEY    RANGE_ROWS  EQ_ROWS DISTINCT_RANGE_ROWS AVG_RANGE_ROWS
1               0           1       0                   1
9999            9997        1       9997                1
10000           0           1       0                   1

Est-ce un problème que l'histogramme ne comporte que 3 étapes? Il semble que les informations soient préservées de notre point de vue. Notez que parce que le type de données est un ENTIER, nous pouvons déterminer le nombre de lignes dans la table pour chaque entier compris entre 1 et 10 000. En règle générale, SQL Server peut le comprendre également, bien qu'il existe certains cas où cela ne fonctionne pas tout à fait . Voir cet article SE pour un exemple de cela.

Que pensez-vous qu'il se passera si nous supprimons une seule ligne du tableau et mettons à jour les statistiques? Idéalement, nous aurions une autre étape d'histogramme pour montrer que l'entier manquant n'est plus dans le tableau.

DELETE FROM X_SEQ_NUM
WHERE X_NUM  = 1000;

UPDATE STATISTICS X_SEQ_NUM X_STATS_SEQ_INT_FULL WITH FULLSCAN;

DBCC SHOW_STATISTICS ('X_SEQ_NUM', 'X_STATS_SEQ_INT_FULL'); -- still 3 steps

DELETE FROM X_SEQ_NUM
WHERE X_NUM  IN (2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000);

UPDATE STATISTICS X_SEQ_NUM X_STATS_SEQ_INT_FULL WITH FULLSCAN;

DBCC SHOW_STATISTICS ('X_SEQ_NUM', 'X_STATS_SEQ_INT_FULL'); -- still 3 steps

C'est un peu décevant. Si nous construisions un histogramme à la main, nous ajouterions une étape pour chaque valeur manquante. SQL Server utilise un algorithme à usage général, donc pour certains ensembles de données, nous pouvons être en mesure de proposer un histogramme plus approprié que le code qu'il utilise. Bien sûr, la différence pratique entre obtenir 0 ou 1 ligne à partir d'une table est très faible. J'obtiens les mêmes résultats lorsque je teste avec 20000 lignes, chaque entier ayant 2 lignes dans le tableau. L'histogramme ne gagne pas de pas lorsque je supprime des données.

RANGE_HI_KEY    RANGE_ROWS  EQ_ROWS DISTINCT_RANGE_ROWS AVG_RANGE_ROWS
1               0           2       0                   1
9999            19994       2       9997                2
10000           0           2       0                   1

Si je teste avec 1 million de lignes avec chaque entier ayant 100 lignes dans le tableau, j'obtiens des résultats légèrement meilleurs, mais je peux toujours construire un meilleur histogramme à la main.

truncate table X_SEQ_NUM;

BEGIN TRANSACTION;
INSERT INTO X_SEQ_NUM WITH (TABLOCK)
SELECT N FROM dbo.GetNums(10000);
GO 100
COMMIT TRANSACTION;

UPDATE STATISTICS X_SEQ_NUM X_STATS_SEQ_INT_FULL WITH FULLSCAN;

DBCC SHOW_STATISTICS ('X_SEQ_NUM', 'X_STATS_SEQ_INT_FULL'); -- 4 steps

DELETE FROM X_SEQ_NUM
WHERE X_NUM  = 1000;

UPDATE STATISTICS X_SEQ_NUM X_STATS_SEQ_INT_FULL WITH FULLSCAN;

DBCC SHOW_STATISTICS ('X_SEQ_NUM', 'X_STATS_SEQ_INT_FULL'); -- now 5 steps with a RANGE_HI_KEY of 998 (?)

DELETE FROM X_SEQ_NUM
WHERE X_NUM  IN (2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000);

UPDATE STATISTICS X_SEQ_NUM X_STATS_SEQ_INT_FULL WITH FULLSCAN;

DBCC SHOW_STATISTICS ('X_SEQ_NUM', 'X_STATS_SEQ_INT_FULL'); -- still 5 steps

Histogramme final:

RANGE_HI_KEY    RANGE_ROWS  EQ_ROWS DISTINCT_RANGE_ROWS AVG_RANGE_ROWS
1               0           100     0                   1
998             99600       100     996                 100
3983            298100      100     2981                100
9999            600900      100     6009                100
10000           0           100     0                   1

Essayons plus loin avec des entiers séquentiels mais avec plus de lignes dans le tableau. Notez que pour les tableaux trop petits, la spécification manuelle d'une taille d'échantillon n'aura aucun effet, je vais donc ajouter 100 lignes dans chaque insert et collecter les statistiques à chaque fois jusqu'à 1 million de lignes. Je vois un modèle similaire à celui précédent, sauf qu'une fois arrivé à 637300 lignes dans le tableau, je n'échantillonne plus 100% des lignes du tableau avec le taux d'échantillonnage par défaut. À mesure que je gagne des lignes, le nombre de pas d'histogramme augmente. C'est peut-être parce que SQL Server se retrouve avec plus de lacunes dans les données à mesure que le nombre de lignes non échantillonnées dans la table augmente. Je ne franchis pas 200 pas, même à 1 M de rangées, mais si je continuais à ajouter des rangées, je m'attendais à y arriver et à recommencer à redescendre.

graphique 2

L'axe des X est le nombre de lignes du tableau. À mesure que le nombre de lignes augmente, les lignes échantillonnées varient un peu et ne dépassent pas 650k.

Faisons maintenant quelques tests simples avec les données VARCHAR.

CREATE TABLE X_SEQ_STR (X_STR VARCHAR(5));
CREATE STATISTICS X_SEQ_STR ON X_SEQ_STR(X_STR);

Ici, j'insère 200 nombres (sous forme de chaînes) avec NULL.

INSERT INTO X_SEQ_STR
SELECT N FROM dbo.GetNums(200)
UNION ALL
SELECT NULL;

UPDATE STATISTICS X_SEQ_STR X_SEQ_STR ;

DBCC SHOW_STATISTICS ('X_SEQ_STR', 'X_SEQ_STR'); -- 111 steps, RANGE_ROWS is 0 or 1 for all steps

Notez que NULL obtient toujours son propre pas d'histogramme lorsqu'il se trouve dans le tableau. SQL Server aurait pu me donner exactement 201 étapes pour conserver toutes les informations, mais il ne l'a pas fait. Techniquement, les informations sont perdues car '1111' est trié entre '1' et '2' par exemple.

Essayons maintenant d'insérer différents caractères au lieu de simples entiers:

truncate table X_SEQ_STR;

INSERT INTO X_SEQ_STR
SELECT CHAR(10 + N) FROM dbo.GetNums(200)
UNION ALL
SELECT NULL;

UPDATE STATISTICS X_SEQ_STR X_SEQ_STR ;

DBCC SHOW_STATISTICS ('X_SEQ_STR', 'X_SEQ_STR'); -- 95 steps, RANGE_ROWS is 0 or 1 or 2

Aucune différence réelle par rapport au dernier test.

Essayons maintenant d'insérer des caractères mais en mettant des nombres différents de chaque caractère dans le tableau. Par exemple, CHAR(11)a 1 ligne, CHAR(12)2 lignes, etc.

truncate table X_SEQ_STR;

DECLARE
@loop_num INT;

BEGIN
    SET NOCOUNT ON;

    SET @loop_num = 0;
    WHILE @loop_num < 200
    BEGIN
        SET @loop_num = @loop_num + 1;

        INSERT INTO X_SEQ_STR WITH (TABLOCK)
        SELECT CHAR(10 + @loop_num) FROM dbo.GetNums(@loop_num);
    END;
END;

UPDATE STATISTICS X_SEQ_STR X_SEQ_STR ;

DBCC SHOW_STATISTICS ('X_SEQ_STR', 'X_SEQ_STR'); -- 148 steps, most with RANGE_ROWS of 0

Comme auparavant, je n'obtiens toujours pas exactement 200 pas d'histogramme. Cependant, la plupart des étapes ont RANGE_ROWS0.

Pour le test final, je vais insérer une chaîne aléatoire de 5 caractères dans chaque boucle et rassembler les statistiques à chaque fois. Voici le code de la chaîne aléatoire:

char((rand()*25 + 65))+char((rand()*25 + 65))+char((rand()*25 + 65))+char((rand()*25 + 65))+char((rand()*25 + 65))

Voici le graphique des lignes du tableau par rapport aux étapes de l'histogramme: graphique 3

Notez que le nombre d'étapes ne descend pas en dessous de 100 une fois qu'il commence à monter et à descendre. J'ai entendu quelque part (mais je ne peux pas le trouver pour le moment) que l'algorithme de construction d'histogramme SQL Server combine les étapes de l'histogramme lorsqu'il manque de place pour eux. Vous pouvez donc vous retrouver avec des changements drastiques dans le nombre d'étapes simplement en ajoutant un peu de données. Voici un échantillon des données que j'ai trouvé intéressantes:

ROWS_IN_TABLE   ROWS_SAMPLED    STEPS
36661           36661           133
36662           36662           143
36663           36663           143
36664           36664           141
36665           36665           138

Même lors de l'échantillonnage avec FULLSCAN, l'ajout d'une seule ligne peut augmenter le nombre d'étapes de 10, la maintenir constante, puis la diminuer de 2, puis la diminuer de 3.

Que pouvons-nous résumer de tout cela? Je ne peux rien prouver de tout cela, mais ces observations semblent être vraies:

  • SQL Server utilise un algorithme d'utilisation générale pour créer les histogrammes. Pour certaines distributions de données, il peut être possible de créer une représentation plus complète des données à la main.
  • S'il y a des données NULL dans la table et que la requête de statistiques les trouve, ces données NULL obtiennent toujours leur propre étape d'histogramme.
  • La valeur minimale trouvée dans le tableau obtient son propre pas d'histogramme avec RANGE_ROWS= 0.
  • La valeur maximale trouvée dans le tableau sera la finale RANGE_HI_KEYdu tableau.
  • À mesure que SQL Server échantillonne davantage de données, il peut être nécessaire de combiner les étapes existantes pour faire de la place aux nouvelles données qu'il trouve. Si vous regardez suffisamment d'histogrammes, vous pouvez voir des valeurs communes se répéter pour DISTINCT_RANGE_ROWSou RANGE_ROWS. Par exemple, 255 apparaît un tas de fois pour RANGE_ROWSet DISTINCT_RANGE_ROWSpour le cas de test final ici.
  • Pour les distributions de données simples, vous pouvez voir SQL Server combiner des données séquentielles en une seule étape d'histogramme qui ne provoque aucune perte d'informations. Cependant, lors de l'ajout de lacunes dans les données, l'histogramme peut ne pas s'ajuster de la manière souhaitée.

Quand est-ce que tout cela pose problème? C'est un problème lorsqu'une requête fonctionne mal en raison d'un histogramme qui n'est pas en mesure de représenter la distribution des données de manière à ce que l'optimiseur de requête prenne de bonnes décisions. Je pense qu'il y a une tendance à penser qu'il est toujours préférable d'avoir plus d'étapes d'histogramme et qu'il y ait consternation lorsque SQL Server génère un histogramme sur des millions de lignes ou plus mais n'utilise pas exactement 200 ou 201 étapes d'histogramme. Cependant, j'ai vu beaucoup de problèmes de statistiques même lorsque l'histogramme comporte 200 ou 201 étapes. Nous n'avons aucun contrôle sur le nombre d'étapes de l'histogramme que SQL Server génère pour un objet de statistiques, donc je ne m'en inquiéterais pas. Cependant, vous pouvez suivre certaines étapes lorsque vous rencontrez des requêtes peu performantes causées par des problèmes de statistiques. Je vais donner un aperçu extrêmement bref.

La collecte complète des statistiques peut aider dans certains cas. Pour les très grands tableaux, la taille d'échantillon automatique peut être inférieure à 1% des lignes du tableau. Parfois, cela peut conduire à de mauvais plans en fonction de la perturbation des données dans la colonne. La documentation de Microsofts pour CREATE STATISTICS et UPDATE STATISTICS en dit autant:

SAMPLE est utile dans les cas particuliers où le plan de requête, basé sur l'échantillonnage par défaut, n'est pas optimal. Dans la plupart des situations, il n'est pas nécessaire de spécifier SAMPLE car l'optimiseur de requête utilise déjà l'échantillonnage et détermine la taille d'échantillon statistiquement significative par défaut, comme requis pour créer des plans de requête de haute qualité.

Pour la plupart des charges de travail, une analyse complète n'est pas requise et l'échantillonnage par défaut est adéquat. Cependant, certaines charges de travail sensibles à des distributions de données très variables peuvent nécessiter une taille d'échantillon accrue, voire une analyse complète.

Dans certains cas, la création de statistiques filtrées peut aider. Vous pouvez avoir une colonne avec des données asymétriques et de nombreuses valeurs distinctes différentes. S'il existe certaines valeurs dans les données qui sont généralement filtrées, vous pouvez créer un histogramme de statistiques uniquement pour ces valeurs communes. L'optimiseur de requêtes peut utiliser les statistiques définies sur une plus petite plage de données au lieu des statistiques définies sur toutes les valeurs de colonne. Vous n'êtes toujours pas garanti d'obtenir 200 étapes dans l'histogramme, mais si vous créez les statistiques filtrées sur une seule valeur, vous obtiendrez une étape d'histogramme cette valeur.

L'utilisation d'une vue partitionnée est un moyen d'obtenir efficacement plus de 200 étapes pour une table. Supposons que vous puissiez facilement diviser une grande table en une seule table par an. Vous créez une UNION ALLvue qui combine toutes les tables annuelles. Chaque table aura son propre histogramme. Notez que les nouvelles statistiques incrémentielles introduites dans SQL Server 2014 permettent uniquement aux mises à jour de statistiques d'être plus efficaces. L'optimiseur de requêtes n'utilisera pas les statistiques créées par partition.

Il existe de nombreux autres tests qui pourraient être exécutés ici, donc je vous encourage à expérimenter. J'ai fait ces tests sur SQL Server 2014 express donc vraiment rien ne vous arrête.

Joe Obbish
la source
4
Voir google.com/patents/US6714938
Paul White 9