SQL Server 主键列统计直方图建议重复值

SEa*_*986 7 sql-server primary-key statistics index-statistics sql-server-2019

我有一个关于表中主键列的统计信息。当我使用默认选项更新统计信息时:

UPDATE STATISTICS dbo.MyTable PK__MyTable__CB394B3946083350
Run Code Online (Sandbox Code Playgroud)

我得到一个直方图如下(删节)

                    RANGE_HI_KEY                      RANGE_ROWS                         EQ_ROWS             DISTINCT_RANGE_ROWS                  AVG_RANGE_ROWS
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
                      3400002201                               0                               1                               0                               1
                      3400009992                        18103.04                               1                            7790                        2.323882
                      3400040033                        26083.68                               1                           26080                        1.000144
                      3400050456                        13029.09                               1                           10422                        1.250153
                      3400087676                        26083.68                               1                           26080                        1.000144
                      3400103858                        19556.38                               1                           16181                        1.208602
                      3400126866                        13029.09                               1                           13029                               1
                      3400162832                        39138.27                               1                           35965                        1.088232
                      3400213115                        45665.56                               1                           45641                        1.000547
                      3400238444                        26083.68                               1                           25328                        1.029836
                      3400242626                        13029.09                               1                            4181                        3.116262
                      3400262174                        19556.38                               1                           19547                         1.00048
                      3400283983                        26083.68                               1                           21808                         1.19606
                      3400304837                        19556.38                               1                           19556                               1
                      3400316046                        13029.09                               1                           11208                        1.162481
                      3400346666                        13029.09                               1                           13029                               1
                      3400368443                        19556.38                               1                           19556                               1
                      3400385634                        26083.68                               1                           17190                        1.517375
                      3400390548                        13029.09                               1                            4913                        2.651962
                      3400398297                        13029.09                               1                            7748                        1.681607
                      3400417467                        13029.09                               1                           13029                               1
                      3400428728                        13029.09                               1                           11260                        1.157113
                      3400462206                        32610.97                               1                           32600                        1.000332
                      3400477978                        13029.09                               1                           13029                               1
                      3400492969                        19556.38                               1                           14990                        1.304629
                      3400507579                        13029.09                               1                           13029                               1
                      3400529627                        32610.97                               1                           22047                        1.479157
                      3400535909                        13029.09                               1                            6281                        2.074366
                      3400556632                        26083.68                               1                           20722                        1.258743
                      3400576037                        19556.38                               1                           19404                        1.007853
                      3400588565                        19556.38                               1                           12527                        1.561139
                      3400630507                        39138.27                               1                           39120                        1.000457
                      3400655236                        19556.38                               1                           19556                               1
                      3400670940                        19556.38                               1                           15703                        1.245392
                      3400691760                        19556.38                               1                           19556                               1
                      3400701959                        19556.38                               1                           10198                        1.917668
                      3400718913                        19556.38                               1                           16953                        1.153565
                      3400745176                        19556.38                               1                           19556                               1
Run Code Online (Sandbox Code Playgroud)

如果我们查看 Hi Key 3400009992,直方图告诉我们:

有一行等于该值 有 18,103 行的值 > 3400002201 且 < 3400009992,但是,在这 18,103 行中,只有 7,790 行是不同的。

怎么会这样?主键必须是唯一的

如果我使用 FULLSCAN 更新统计数据,我会得到下面的直方图(完整),它似乎准确地表示了数据

                RANGE_HI_KEY                      RANGE_ROWS                         EQ_ROWS             DISTINCT_RANGE_ROWS                  AVG_RANGE_ROWS
----------------------------------------------------------------------------------------------------------------------------------------------------------------
                      3400000000                               0                               1                               0                               1
                      3401474769                         1474758                               1                         1474758                               1
                    600004687218                           16383                               1                           16383                               1
                    600005089447                           65535                               1                           65535                               1
                    600005665352                           98303                               1                           98303                               1
                    600006294532                           81919                               1                           81919                               1
                    600008729190                          294911                               1                          294911                               1
                    600012125564                          425983                               1                          425983                               1
                    600014952842                          376831                               1                          376831                               1
                    600017609236                          344063                               1                          344063                               1
                    600017776836                           24575                               1                           24575                               1
                    600022385710                          598015                               1                          598015                               1
                    600022698873                           38234                               1                           38234                               1
                    600022698878                               0                               1                               0                               1
Run Code Online (Sandbox Code Playgroud)

为什么SQL Server的采样直方图不能代表主键的唯一性?

Pau*_*ite 6

KB3202425 -改进:通过更改 UNIQUE 列上直方图的使用来提高 SQL Server 2016 的查询性能

改进

在 Microsoft SQL Server 2016 当前的基数估计模型中,缩放直方图时不会解释唯一性。这可能会导致唯一列的频率大于1RTM 中处理此问题的方法是完全忽略UNIQUE列上的直方图。当列的分布不均匀时,这可能会导致估计值不佳。

安装此更新后,如果直方图的所有步长值在唯一值的 10% 以内,则可以正确使用直方图。

笔记

仅当启用跟踪标志 4199、数据库配置 QUERY_OPTIMIZER_HOTFIXES 的数据库范围设置为 ON 或使用查询提示 ENABLE_QUERY_OPTIMIZER_HOTFIXES 时,才会启用此更改。

从 SQL Server 2016 SP1 开始,ENABLE_QUERY_OPTIMIZER_HOTFIXES 查询提示可用。

正如现代知识库中经常出现的那样,您必须想象它们真正想要传达的含义:

直方图缩放时无法解释唯一性

人们可以理解,这意味着采样统计直方图(这是唯一需要“缩放”的类型)不反映任何唯一性约束,这是您问题的核心。


如果将数据库兼容性级别设置为 120 或更早,则会出现有趣的差异。这显然不仅仅影响统计抽样。例如,在 SQL Server 2019 CU 19 上使用2010 Stack Overflow 示例数据库

USE StackOverflow2010;
GO
ALTER DATABASE StackOverflow2010 SET COMPATIBILITY_LEVEL = 150;
GO
UPDATE STATISTICS dbo.Posts (PK_Posts__Id);
GO
SELECT TOP (5) 
    H.step_number,
    H.range_high_key,
    H.range_rows,
    H.equal_rows,
    H.distinct_range_rows,
    H.average_range_rows
FROM sys.tables AS T
JOIN sys.schemas AS SCH
    ON SCH.[schema_id] = T.[schema_id]
JOIN sys.indexes AS I
    ON I.[object_id] = T.[object_id]
JOIN sys.stats AS S
    ON S.[object_id] = T.[object_id]
    AND S.stats_id = I.index_id
CROSS APPLY sys.dm_db_stats_histogram
(
    S.[object_id],
    S.stats_id
) AS H
WHERE
    SCH.[name] = N'dbo'
    AND T.[name] = N'Posts'
    AND I.[type_desc] = N'CLUSTERED'
ORDER BY
    H.step_number ASC;
Run Code Online (Sandbox Code Playgroud)
步骤号 范围高调 范围行数 相等行数 不同范围行 平均范围行数
1 467 0 1 0 1
2 471 111.9387 1 3 37.31289
3 594 167.908 1 122 1.376295
4 5071 1735.05 1 1735 1
5 11035 3078.314 1 3078 1

将上述脚本中的兼容性级别150替换为120

步骤号 范围高调 范围行数 相等行数 不同范围行 平均范围行数
1 467 0 1 0 1
2 51352 25401.67 1 25402 1
3 115718 42914.28 1 42888 1.000605
4 141859 14267.46 1 14267 1
5 161001 14267.46 1 14267 1

注意range_rowsdistinct_range_rows更接近于相等。

仔细想想,这可能是因为 CL 120 不允许并行统计更新,但无论如何我都会保留该示例。如果你搞乱了可选MAXDOP子句 for ,你可以在 CL150 下看到类似的差异UPDATE STATISTICS


正如我一开始所说的,这是部分解释。只有能够访问源代码和内部设计文档的人才能准确地告诉您事情如何以及为何发生变化。

据推测,这都是正在进行的工作的一部分,目的是使选择性估计更加一致且更易于维护。我认为可以公平地说,到目前为止,这还不是一个彻底的成功故事。

相关问答:

  • @SE1986 我添加了更多单词和示例。正如我一开始所说的,这是部分解释。只有有权访问源代码和内部设计文档的人才能准确地告诉您事情如何以及“为什么”发生了变化。 (2认同)