Azure SQL DW 在没有统计的情况下如何知道行数?

How does Azure SQL DW know the row count without statistics?

如果我 运行 创建外部 TABLE cetasTable AS SELECT 命令然后 运行:

EXPLAIN
select * from cetasTable

我在分布式查询计划中看到:

<operation_cost cost="4231.099968" accumulative_cost="4231.099968" average_rowsize="2056" output_rows="428735" />

它似乎知道正确的行数,但是,如果我看没有在该 table 上创建统计信息,因为此查询 returns 零行:

select * from sys.stats where object_id = object_id('cetasTable')

如果我已经在 blob 存储中有文件并且我 运行 一个 CREATE EXTERNAL TABLE cetTable 命令然后 运行:

EXPLAIN
select * from cetTable 

分布式查询计划显示SQL DW认为外部只有1000行table:

  <operation_cost cost="4.512" accumulative_cost="4.512" average_rowsize="940" output_rows="1000" />

当然我可以创建统计信息以确保 SQL DW 在创建分布式查询计划时知道正确的行数。但是有人能解释一下它是如何在某些时候知道正确的行数以及正确的行数存储在哪里的吗?

您看到的是使用 CxTAS(CTAS、CETAS 或 CRTAS)创建的 table 与创建 TABLE.

之间的区别

当您 运行 CREATE TABLE 时,行数和页数值是固定的,因为 table 是空的。如果内存服务,则固定值为 1000 行和 100 页。当您使用 CTAS 创建 table 时,它们并没有被修复。 CTAS 命令知道实际值,因为它刚刚在单个命令中创建并填充了 table。因此,当使用 CxTAS 时,元数据正确地反映了 table SIZE。这很好。当通过 CxTAS 创建 table 而不是 CREATE table .

准确了解 table 大小很重要。

假设您使用 CREATE TABLE 创建了一个 table,然后使用 INSERT 将 10 亿行插入到所述 table 中。 shell 数据库仍然认为 table 有 1000 行和 100 页。然而,事实显然并非如此。这样做的原因是因为 table size 属性此时不会自动更新。

现在假设触发了一个需要在此 table 上移动数据的查询。事情可能会开始出错。您现在更有可能看到引擎做出糟糕的 MPP 计划选择(通常使用 BROADCAST 而不是 SHUFFLE),因为它不理解 table 大小等等。

你能做些什么来改善这一点?

您为每个 table 创建了至少一个列级统计对象。一般来说,您将在查询中的 JOINS、GROUP BY、WHERE 和 ORDER BY 中使用的所有列上创建统计对象。稍后我将解释统计数据生成的基本过程。我只想强调,这里的号召性用语是确保您创建和维护您的统计对象。

当为列执行 CREATE STATISTICS 时,实际上会发生三个事件。

1)Table级别信息在CONTROL节点更新

2) 在 COMPUTE 节点上的每个分布上创建列级统计对象

3) 在CONTROL节点上创建和更新列级统计对象

1)Table级别信息在CONTROL节点上更新

第一步是更新table等级信息。为此,APS / SQLDW 对每个物理分布执行 DBCC SHOW_STATISTICS (table_name) WITH STAT_STREAM;合并结果并将它们存储在 shell 数据库的目录元数据中。行数保持在 sys.partitions,页数保持在 sys.allocation_units。 Sys.partitions 在 SQLDW 和 APS 中对您可见。但是,此时 sys.allocation_units 对最终用户不可见。对于那些熟悉 SQL 服务器内部结构的人,我引用了该位置以获取信息和上下文。

在此阶段结束时,CONTROL 节点上 shell 数据库中保存的元数据已更新行数和页数。现在,由 CREATE TABLE 创建的 table 和 CTAS 之间没有区别 - 两者都知道大小。

2) 在 COMPUTE 节点上的每个分布上创建列级统计对象

必须在每个 COMPUTE 节点上的每个分布中创建统计对象。通过创建一个重要的统计对象,为该列创建了详细的统计数据(特别是直方图和密度向量)。

APS 和 SQLDW 使用此信息生成分布级 SMP 计划。 SMP 计划仅由 APS / SQLDW 在物理层中使用。因此,此时统计数据不在可用于生成 MPP 计划的位置。信息是分布式的,无法及时访问以进行基于成本的优化。因此需要第三步...

3) 在CONTROL节点上创建和更新列级统计对象

一旦在计算层中的分布上物理地创建了数据,就必须将其放在一起并逻辑地保存,以促进基于 MPP 计划成本的优化。 CONTROL 节点上的 shell 数据库也创建了一个统计对象。这是统计对象的逻辑表示。

但是,shell 数据库统计信息尚未反映在计算节点上的分布中物理保存的列级统计信息。因此,CONTROL 节点上 shell 数据库中的统计对象需要在创建后立即更新。

DBCC SHOW_STATISTICS (table_name, stat_name) WITH STAT_STREAM 用于执行此操作。

注意该命令有第二个参数。这改变了结果集;为 APS / SQLDW 提供为该列构建统计对象的逻辑视图所需的所有信息。

我希望这能以某种方式解释您所看到的内容,以及如何创建统计信息以及为什么它们对 Azure SQL DW 和 APS 很重要。