您看到的是使用 CxTAS(CTAS、CETAS 或 CRTAS)创建的表与 CREATE TABLE 之间的区别。
当您运行 CREATE TABLE 时,行计数和页计数值是固定的,因为表是空的。如果内存服务固定值是 1000 行和 100 页。当您使用 CTAS 创建表时,它们不是固定的。CTAS 命令知道实际值,因为它刚刚在单个命令中创建并填充了表。因此,当使用 CxTAS 时,元数据正确地反映了表 SIZE。这很好。当通过 CxTAS 创建表而不是通过 CREATE 表创建表时,基于 APS / SQLDW 成本的优化器可以立即根据表 SIZE 更好地估计 MPP 计划生成。
准确了解表大小很重要。
想象一下,您有一个使用 CREATE TABLE 创建的表,然后使用 INSERT 将 10 亿行插入到该表中。shell 数据库仍然认为该表有 1000 行和 100 页。然而,情况显然并非如此。这样做的原因是因为此时表大小属性不会自动更新。
现在想象一个查询被触发,需要在这个表上移动数据。事情可能会开始出错。您现在更有可能看到引擎做出糟糕的 MPP 计划选择(通常使用 BROADCAST 而不是 SHUFFLE),因为它不了解表大小等。
你能做些什么来改善这一点?
每个表至少创建一个列级统计对象。一般来说,您将在查询中的 JOINS、GROUP BY、WHERE 和 ORDER BY 中使用的所有列上创建统计对象。稍后我将解释统计信息生成的基本过程。我只想强调,这里的号召性用语是确保您创建和维护您的统计对象。
当为列执行 CREATE STATISTICS 时,实际上会发生三个事件。
1) 表级信息在 CONTROL 节点上更新
2) 在计算节点上的每个分布上创建列级统计对象
3) 在 CONTROL 节点上创建和更新列级统计对象
1) 表级信息在 CONTROL 节点上更新
第一步是更新表级信息。为此,APS / SQLDW 对每个物理分布执行 DBCC SHOW_STATISTICS (table_name) WITH STAT_STREAM;合并结果并将它们存储在 shell 数据库的目录元数据中。行数保存在 sys.partitions 上,页数保存在 sys.allocation_units 上。Sys.partitions 在 SQLDW 和 APS 中对您都是可见的。但是,此时最终用户看不到 sys.allocation_units。我为那些熟悉 SQL Server 内部的人参考了该位置以获取信息和上下文。
在此阶段结束时,控制节点上的 shell 数据库中保存的元数据已针对行数和页数进行了更新。现在由 CREATE TABLE 创建的表和 CTAS 之间没有区别 - 两者都知道大小。
2) 在计算节点上的每个分布上创建列级统计对象
必须在每个 COMPUTE 节点上的每个分布中创建统计对象。通过创建重要的统计对象,已创建列的详细统计数据(特别是直方图和密度向量)。
APS 和 SQLDW 使用此信息来生成分布级别的 SMP 计划。APS / SQLDW 仅在物理层中使用 SMP 计划。因此,此时统计数据不在可用于生成 MPP 计划的位置。信息是分发的,并且无法及时访问以进行基于成本的优化。因此需要第三步...
3) 在 CONTROL 节点上创建和更新列级统计对象
一旦数据在 COMPUTE 层的分布上以物理方式创建,它必须被汇集在一起并以逻辑方式保存,以促进基于 MPP 计划成本的优化。CONTROL 节点上的 shell 数据库也创建了一个统计对象。这是统计对象的逻辑表示。
但是,shell 数据库 stat 尚未反映在 COMPUTE 节点上的分布中物理保存的列级统计信息。因此,在 CONTROL 节点上的 shell 数据库中的统计信息对象需要在创建后立即更新。
DBCC SHOW_STATISTICS (table_name, stat_name) WITH STAT_STREAM 用于执行此操作。
请注意,该命令有第二个参数。这会改变结果集;为 APS / SQLDW 提供为该列构建统计对象的逻辑视图所需的所有信息。
我希望这有助于解释您所看到的内容,以及如何创建统计信息以及为什么它们对 Azure SQL DW 和 APS 很重要。