如果我运行 CREATE EXTERNAL TABLE cetasTable AS SELECT 命令,然后运行:
EXPLAIN
select * from cetasTable
Run Code Online (Sandbox Code Playgroud)
我在分布式查询计划中看到:
<operation_cost cost="4231.099968" accumulative_cost="4231.099968" average_rowsize="2056" output_rows="428735" />
Run Code Online (Sandbox Code Playgroud)
它似乎知道正确的行数,但是,如果我查看该表上没有创建统计信息,因为此查询返回零行:
select * from sys.stats where object_id = object_id('cetasTable')
Run Code Online (Sandbox Code Playgroud)
如果 Blob 存储中已有文件并且运行 CREATE EXTERNAL TABLE cetTable 命令,则运行:
EXPLAIN
select * from cetTable
Run Code Online (Sandbox Code Playgroud)
分布式查询计划显示 SQL DW 认为外部表中只有 1000 行:
<operation_cost cost="4.512" accumulative_cost="4.512" average_rowsize="940" output_rows="1000" />
Run Code Online (Sandbox Code Playgroud)
当然,我可以创建统计信息以确保 SQL DW 在创建分布式查询计划时知道正确的行数。但是有人可以解释它如何在某些时候知道正确的行数以及正确的行数存储在哪里吗?
小智 4
您看到的是使用 CxTAS(CTAS、CETAS 或 CRTAS)创建的表与 CREATE TABLE 之间的区别。
当您运行 CREATE TABLE 时,行计数和页计数值将被固定,因为表为空。如果内存可用,则固定值为 1000 行和 100 页。当您使用 CTAS 创建表时,它们不是固定的。CTAS 命令已知实际值,因为它刚刚在单个命令中创建并填充了表。因此,当使用 CxTAS 时,元数据正确反映表 SIZE。这很好。当通过 CxTAS(而不是 CREATE 表)创建表时,基于表 SIZE 的 APS / SQLDW 基于成本的优化器可以立即对 MPP 计划生成进行更好的估计。
准确了解桌子尺寸很重要。
想象一下,您使用 CREATE TABLE 创建了一个表,然后使用 INSERT 将 10 亿行插入到该表中。shell数据库仍然认为该表有1000行和100页。然而,事实显然并非如此。出现这种情况的原因是因为此时表大小属性不会自动更新。
现在想象一下,触发了一个查询,需要在此表上移动数据。事情可能会开始出错。您现在更有可能看到引擎做出糟糕的 MPP 计划选择(通常使用 BROADCAST 而不是 SHUFFLE),因为它不了解表大小等。
你能做些什么来改善这一点?
您为每个表至少创建一个列级统计对象。一般来说,您将在查询中的 JOINS、GROUP BY、WHERE 和 ORDER BY 中使用的所有列上创建统计对象。我稍后将解释统计数据生成的基本过程。我只是想强调,这里的号召性用语是确保您创建和维护统计对象。
当对列执行 CREATE STATISTICS 时,实际上会发生三个事件。
1)表级别信息在CONTROL节点上更新
2) 在 COMPUTE 节点上的每个分布上创建列级统计对象
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 内部结构的人员参考了该位置以获取信息和上下文。
在此阶段结束时,CONTROL 节点上的 shell 数据库中保存的元数据已更新为行数和页数。现在,由 CREATE TABLE 创建的表和 CTAS 创建的表之间没有区别 - 两者都知道大小。
2) 在 COMPUTE 节点上的每个分布上创建列级统计对象
必须在每个 COMPUTE 节点上的每个分布中创建统计对象。通过创建统计对象,已为该列创建了重要、详细的统计数据(特别是直方图和密度向量)。
APS 和 SQLDW 使用此信息来生成分发级别 SMP 计划。SMP 计划仅由 APS / SQLDW 在 PHYSICAL 层使用。因此,此时统计数据并不位于可用于生成 MPP 计划的位置。信息是分布式的,无法及时访问以实现基于成本的优化。因此,第三步是必要的......
3)在CONTROL节点上创建并更新列级统计对象
一旦在计算层的分布上物理地创建了数据,就必须将其汇集在一起并逻辑地保存,以促进基于 MPP 计划成本的优化。CONTROL 节点上的 shell 数据库也会创建一个统计对象。这是统计对象的逻辑表示。
但是,shell 数据库统计信息尚未反映在 COMPUTE 节点上的分布中物理保存的列级统计信息。因此,CONTROL 节点上的 shell 数据库中的统计对象在创建后需要立即更新。
DBCC SHOW_STATISTICS (table_name, stat_name)WITH STAT_STREAM 用于执行此操作。
请注意,该命令有第二个参数。这会改变结果集;为 APS / SQLDW 提供构建该列的统计对象的逻辑视图所需的所有信息。
我希望这能在一定程度上解释您所看到的内容以及如何创建统计信息以及为什么它们对于 Azure SQL DW 和 APS 很重要。
| 归档时间: |
|
| 查看次数: |
1540 次 |
| 最近记录: |