为什么SQL Server不做复合列统计直方图?


10

SQL Server有一个叫做“多列统计”的东西,但这不是人们想的那样。

让我们看下面的示例表:

CREATE TABLE BadStatistics 
(
    IsArchived BIT NOT NULL,
    Id INT NOT NULL IDENTITY PRIMARY KEY,
    Mystery VARCHAR(200) NOT NULL
);

CREATE NONCLUSTERED INDEX BadIndex 
    ON BadStatistics (IsArchived, Mystery);

这样,将在我们拥有的两个索引上创建两个统计信息:

BadIndex的统计信息:

+--------------+----------------+-------------------------+
| All density  | Average Length | Columns                 |
+--------------+----------------+-------------------------+
| 0.5          | 1              | IsArchived              |
+--------------+----------------+-------------------------+
| 4.149378E-06 | 37             | IsArchived, Mystery     |
+--------------+----------------+-------------------------+
| 4.149378E-06 | 41             | IsArchived, Mystery, Id |
+--------------+----------------+-------------------------+

+--------------+------------+---------+---------------------+----------------+
| RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | AVG_RANGE_ROWS |
+--------------+------------+---------+---------------------+----------------+
| 0            | 0          | 24398   | 0                   | 1              |
+--------------+------------+---------+---------------------+----------------+
| 1            | 0          | 216602  | 0                   | 1              |
+--------------+------------+---------+---------------------+----------------+

聚集索引的统计信息:

+--------------+----------------+---------+
| All density  | Average Length | Columns |
+--------------+----------------+---------+
| 4.149378E-06 | 4              | Id      |
+--------------+----------------+---------+

+--------------+------------+---------+---------------------+----------------+
| RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | AVG_RANGE_ROWS |
+--------------+------------+---------+---------------------+----------------+
| 1            | 0          | 1       | 0                   | 1              |
+--------------+------------+---------+---------------------+----------------+
| 240999       | 240997     | 1       | 240997              | 1              |
+--------------+------------+---------+---------------------+----------------+
| 241000       | 0          | 1       | 0                   | 1              |
+--------------+------------+---------+---------------------+----------------+

(我在表中填充了随机样本数据,其中大约十分之一的行未​​归档。此后,我运行了一次完整的扫描统计信息更新。)

为什么两栏统计的直方图只使用一列?我知道,很多人都写关于它,但有什么道理呢?在这种情况下,由于第一列只有两个值,因此它使整个直方图的使用效率大大降低。为什么会像这样任意限制统计数据?

请注意,这个问题不是针对多维直方图,它是完全不同的野兽。它是关于一维直方图,其中一维是包含各自的多个列的元组。

Answers:


8

背景

当前的SQL Server模型仅使用单列直方图和多列密度信息。单列直方图用于估计适当谓词(例如a = 1或)的选择性b > 50。具有多个谓词的查询仅将各个选择性(带有假设)组合在一起即可产生估计的整体选择性。

有关示例,请参阅我的文章“ 基数估计:合并密度统计”

多列密度通过为多个等式谓词提供弱相关信息并为聚合提供基数分组进一步为模型提供信息。

与索引关联的统计信息是该模型的一个机会附加组件:引擎在构建索引时也可能会收集(通常是全扫描)统计信息。SQL Server自动为其他键构​​造前导柱状图和密度信息。

索引中非前导列的直方图可以由查询处理器根据需要自动构建,也可以事先sp_createstats@indexonly选项一起使用(除其他外)。

多列直方图

结合单列统计信息(如上所述)时所做的假设可能会或可能不会足够好地模拟数据的真实性。在许多情况下,可用的选项(指数补偿,独立性,最小选择性)产生“足够好”的估计。

我们还过滤了统计信息(和索引)作为低基数前导列索引的自然解决方案,例如在问题示例中。将这些问题推向逻辑极限会使我们更接近问题所不关涉的多维统计。

当可用的建模选项无法提供合适的估计时,在某些情况下,多列统计直方图确实可以为合适的索引谓词提供更好的选择性估计。将不同的数据类型合并到不同的列中会遇到一些困难,但是没有不可克服的困难。

我们还需要为每个级别的索引键创建一个直方图(以获得最佳结果);所以对于一个索引(a, b, c),这将意味着在直方图(a, b)(a, b, c)除对当前单列直方图(a)孤单。

还需要修改用于检测过时统计信息的机制,以维护受影​​响的多列直方图。这些直方图可能会比单列统计信息更频繁地重建,这仅仅是因为对更多列的修改会影响它们。

所有这些都增加了尺寸,复杂性和维护开销。

可以使用在精心构造的,引用多个列的计算列上创建的统计信息(在一定程度上)模拟多列统计信息。该查询将需要在计算列上包含谓词(或与基础公式完全匹配的文本)才能利用该统计信息。仅在非常有限的情况下,该方法才可行。但是,它具有与自动多列直方图相同的实现问题。

最终,唯一可以肯定地说出SQL Server不支持多列统计信息的人将是设计者自己。如果您认为可以广泛应用该领域的产品改进,可以在Connect上或通过常规支持渠道提出建议。

脚注

在这种情况下,它会使整个直方图的使用效率大大降低,因为第一列只有两个值

直方图还提供了有关值的前导列分布的有用信息:当统计建成,共有24,398行,其中IsArchived假的,和216602行哪里是

此外,统计资料对象告诉我们,(1 / 0.5)= 2个不同值IsArchived,(1 / 4.149378E-06)〜= 241000个不同值,(IsArchived, Mystery)平均行大小为37个字节,而(IsArchived, Mystery, Id)使用每行4个额外字节。

这些都是很好的通用信息,可以将其与其他列的统计信息结合使用,以在具有多个谓词的查询中生成选择性估计(如上所述)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.