Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
行组质量取决于行组中的行数。 增加可用内存可以使列存储索引压缩到每个行组中的行数最大化。 使用这些方法可提高列存储索引的压缩率和查询性能。
由于列存储索引通过扫描各个行组的列段来扫描表,最大程度地提高每个行组中的行数可以提高查询性能。
当行组具有大量行时,数据压缩会改进,这意味着从磁盘读取的数据较少。
有关行组的详细信息,请参阅 列存储索引指南。
为了获得最佳查询性能,目标是最大化列存储索引中每行组的行数。 行组最多可以有 1,048,576 行。
每个行组不一定要具有最大行数。 当行组至少有 100,000 行时,列存储索引的性能良好。
在大容量加载或列存储索引重新生成期间,有时没有足够的内存可用于压缩为每个行组指定的所有行。 如果存在内存压力,列存储索引会调整行组大小,以确保能够成功压缩到列存储中。
如果内存不足,无法将至少 10,000 行压缩到每个行组中,将生成错误。
有关批量加载的详细信息,请参阅 Bulk load into a clustered columnstore index(批量加载到聚集列存储索引中)。
DMV sys.dm_pdw_nodes_db_column_store_row_group_physical_stats(sys.dm_db_column_store_row_group_physical_stats 包含与 SQL DB 匹配的视图定义),用于公开一些有用信息,例如行组中的行数,以及修整原因(如果有过修整)。
可创建下列视图来轻松查询此 DMV,以便获得关于行组修整的信息。
create view dbo.vCS_rg_physical_stats
as
with cte
as
(
select tb.[name] AS [logical_table_name]
, rg.[row_group_id] AS [row_group_id]
, rg.[state] AS [state]
, rg.[state_desc] AS [state_desc]
, rg.[total_rows] AS [total_rows]
, rg.[trim_reason_desc] AS trim_reason_desc
, mp.[physical_name] AS physical_name
FROM sys.[schemas] sm
JOIN sys.[tables] tb ON sm.[schema_id] = tb.[schema_id]
JOIN sys.[pdw_table_mappings] mp ON tb.[object_id] = mp.[object_id]
JOIN sys.[pdw_nodes_tables] nt ON nt.[name] = mp.[physical_name]
JOIN sys.[dm_pdw_nodes_db_column_store_row_group_physical_stats] rg ON rg.[object_id] = nt.[object_id]
AND rg.[pdw_node_id] = nt.[pdw_node_id]
AND rg.[distribution_id] = nt.[distribution_id]
)
select *
from cte;
trim_reason_desc指示行组是否已剪裁(trim_reason_desc = NO_TRIM表示没有剪裁,行组质量最佳)。 下列修整原因指示行组的过早修整:
- BULKLOAD:当加载的行的传入批小于 100 万行时,使用此修整原因。 如果插入的行数(而不是插入增量存储)大于 100,000,引擎将创建压缩的行组,但会将修整原因设置为 BULKLOAD。 在此方案中,请考虑增加批处理负载以包含更多行。 另外,请重新评估分区方案,避免其太过细化,因为行组无法跨越分区边界。
- MEMORY_LIMITATION:若要创建包含 100 万行的行组,引擎需要一定数量的工作内存。 当加载会话的可用内存小于所需的工作内存时,将提前修整行组。 以下部分介绍如何估算所需的内存并分配更多内存。
- DICTIONARY_SIZE:此修整原因指示,由于至少有一个字符串列具有宽和/或高基数字符串,因此发生行组修整。 字典大小在内存中限制为 16 MB,达到此限制后,将压缩行组。 如果确实遇到这种情况,请考虑将有问题的列隔离到单独的表中。
压缩一个行组所需的最大内存大约是
- 72 MB +
- #rows * #columns * 8 字节 +
- #rows * #short-string-columns * 32 字节 +
- #long-string-columns * 16 MB 用于压缩字典
Nota
短字符串列使用 = 32 字节的 <字符串数据类型,长字符串列使用 32 字节的 > 字符串数据类型。
长字符串使用用于压缩文本的压缩方法进行压缩。 此压缩方法使用 字典 来存储文本模式。 字典的最大大小为 16 MB。 行组中每个长字符串列只能有一个词典。
使用以下技术来减少将行组压缩为列存储索引的内存要求。
如果可能,请设计包含更少列的表。 将行组压缩到列存储中时,列存储索引会单独压缩每个列段。
因此,压缩行组的内存要求随着列数的增加而增加。
字符串数据类型的列需要比数值和日期数据类型更多的内存。 若要降低内存需求,请考虑从事实数据表中删除字符串列,并将其放入较小的维度表中。
字符串压缩的其他内存要求:
- 最多 32 个字符的字符串数据类型可能需要每个值 32 个额外的字节。
- 使用字典方法压缩超过 32 个字符的字符串数据类型。 行组中的每列最多可能需要 16 MB 才能生成字典。
列存储索引为每个分区创建一个或多个行组。 对于 Azure Synapse Analytics 中的专用 SQL 池,分区数会很快增长,因为数据已分布,并且每个分布区都已分区。
如果表的分区过多,则可能没有足够的行来填充行组。 如果缺少行,在压缩过程中不会产生内存不足的情况。 但是,这会导致行组未达到最佳列存储查询性能。
避免过度分区的另一个原因是,分区表的列存储索引在加载行时会产生额外的内存开销。
在加载期间,多数分区可能会收到传入行,它们会保存在内存中,直到每个分区都有足够行可进行压缩。 分区过多会产生额外的内存压力。
数据库在查询中的所有运算符之间共享查询的内存授予。 当负载查询具有复杂的排序和联接时,可用于压缩的内存会减少。
设计加载查询时,应重点关注查询的加载。 如果需要对数据运行转换,请将它们与加载查询分开运行。 例如,将数据暂存在一个堆表中,运行转换,并将临时表加载到列存储索引中。
Sugerencia
还可以先加载数据,然后使用 MPP 系统转换数据。
当每个分布有多个 CPU 核心可用时,每个分布会将行组并行压缩到列存储中。
并行处理需要额外的内存资源,这可能会导致内存压力和行组裁剪。
若要降低内存压力,可以使用 MAXDOP 查询提示来强制负载作在每个分发中以串行模式运行。
CREATE TABLE MyFactSalesQuota
WITH (DISTRIBUTION = ROUND_ROBIN)
AS SELECT * FROM FactSalesQuota
OPTION (MAXDOP 1);
DWU 大小和用户资源类共同确定用户查询可用的内存量。
若要增加负载查询的内存授予,可以增加 DWU 数或增加资源类。
- 若要增加 DWU,请参阅 如何调整性能?
- 若要更改查询的资源类,请参阅 “更改用户资源类”示例。
若要查找提高专用 SQL 池性能的更多方法,请参阅 性能概述。