聚集列存储索引上的 Trim_reason = DICTIONARY_SIZE

Hen*_*sen 4 sql-server columnstore sql-server-2019

在包含 170 亿行的分区表上,我得到的 row_group 数量非常多。
我听说我应该尝试在每个行组中获取 1.048.576 行。我该如何实现这一目标?

据报道,这trim_reason是。DICTIONARY_SIZEsys.dm_db_column_store_row_group_physical_stats

当我的批处理作业每批插入 1,048,576 行时,每个行组平均获得 100.000 行。

我对列存储索引相当陌生,但我能找到的唯一参考DICTIONARY_SIZE是字符串列。我的表只有bitbigint、 和numeric列。

我的表看起来像这样(列名模糊),我知道很多列大多包含 NULL。如果存在值,它们可能会变化很大(标准差很大)。这是振动数据。

CREATE TABLE fct.MeasureV2
(
MeasureV2ID bigint NOT NULL IDENTITY(1, 1),
DT1ModelID int NOT NULL CONSTRAINT DF_MeasureV2_DT1ModelID DEFAULT ((0)),
DT1TID int NOT NULL CONSTRAINT DF_MeasureV2_DT1TID DEFAULT ((0)),
TimeStampUTC datetime NOT NULL,
AChkSum bigint NULL,
OChkSum bigint NULL,
SChkSum bigint NULL,
ATp numeric (18, 10) NULL,
ATpAvg numeric (18, 10) NULL,
AWDAbsAvg numeric (18, 10) NULL,
G1TMF numeric (18, 10) NULL,
G2Ps_1TMF numeric (18, 10) NULL,
G2Ps_2TMF numeric (18, 10) NULL,
/* about 600 more numeric (18, 10) NULL columns */
WdSdv numeric (18, 10) NULL,
UpdatedDate datetime NOT NULL,
UpdatedID bigint NULL,
IsCorrected bit NOT NULL CONSTRAINT DF_MeasureV2_IsCorrected DEFAULT ((0)),
TRATransformJobID int NOT NULL
) ON PS_FctMeasure (TimeStampUTC)
GO
CREATE CLUSTERED COLUMNSTORE INDEX CCI_MeasureV2 ON fct.MeasureV2 ON PS_FctMeasure (TimeStampUTC)
GO
Run Code Online (Sandbox Code Playgroud)

有很多列,但替代属性值表将包含超过 2000 亿行,并且几乎不可能查询。这种格式很慢,但也不算太慢。
我们还尝试过SPARSE列,但这占用了大量磁盘空间。

Pau*_*ite 8

我听说我应该尝试在每个 row_group 中获取 1,048,576 行。

这是一个理想,但在实践中并不总是可以实现。无论如何,这通常不是您应该关注的主要因素。

...我能找到的唯一参考DICTIONARY_SIZE是字符串列

使用长字符串列可以更轻松地演示字典压力,仅此而已。

字典编码适用于所有数据类型。另一种基于值的编码仅适用于数字类型(广义上)。

值编码通过缩放和重新确定数值的基础来工作。例如,值 {1100, 1200, 1300} 可以存储为 (0, 1, 2),首先按 0.01 倍缩放得到 {11, 12, 13},然后从 11 变基得到 {0, 1, 2}。

使用字典编码,每个唯一值都存储在字典中并分配一个整数 id。然后,段数据引用字典中的 ID 号而不是原始值。

使用字典时,主字典存储整个列的值。可以为列的每个段(即每个行组)创建附加的辅助字典。

字典的最大内存大小为 16MB。持久存储时它会被压缩。如果字典已满,则在列存储构建期间行组的大小会自动减小。

但请注意,如果同一线程负责构建多个行组,则同一辅助字典可能会被多个行组引用。如果该字典达到其最大大小,则引用它的所有行组的大小也将受到限制。

如果共享辅助字典导致行组大小限制,您可以尝试在启用全局跟踪标志 11612 的情况下重建列存储索引:

DBCC TRACEON (11612, -1);
Run Code Online (Sandbox Code Playgroud)

此跟踪标志可防止辅助字典共享。

您可以找到 中使用的编码类型sys.column_store_segments

字典的类型及其关联的数据可以从 中找到sys.column_store_dictionaries

对于固定的架构和数据集,您几乎无法影响 SQL Server 使用的编码类型和压缩方案。

即使您可以更改架构或数据集,在给定所提供的信息并且不知道您运行的查询类型的情况下,也很难说出您应该做什么。您的数据可能并不最适合列存储压缩,但这并不意味着它不是更好的解决方案之一。例如,您可能会考虑使用数据湖。如果您需要设计建议,我建议您提出一个新问题,并提供尽可能多的相关细节。

如果您的列存储已经分区良好并且在实践中表现得足够好,那么我不会太担心由于字典大小限制而导致的较小行组。

避免增量存储、在运行时实现分区/行组消除(如果可能)以及聚合下推通常更为重要。