2

在 Azure 数据仓库中,建议对计划加入甚至可能聚合的字段上的分布式表使用 HASH。还建议您在计划使用的字段上创建统计信息。

假设您有两个具有相同数量的记录和字段的表。一个表在一个非常唯一的键上散列,另一个是 ROUND_ROBIN,其中数据在 60 个数据库中随机平均分配。

-- CustomerID is alphanumeric
SELECT
   [ProductID]
  ,COUNT(DISTINCT [CustomerID]) AS [Unique Records]
FROM [dbo].[FactTable]
GROUP BY
   [Product]

在散列表上,如果您对散列键进行聚合,您可以看到它在 0.05 秒内返回结果。在轮询表上,使用相同的聚合,它是 0.51 秒。

CREATE STATISTICS [ProductID] ON [dbo].[FactTable] ([ProductID]);
CREATE STATISTICS [CustomerID] ON [dbo].[FactTable] ([CustomerID]);

当您将统计信息应用于您正在聚合的字段时,散列表仍会在 0.05 秒内返回。没变。当您对循环表执行相同操作时,结果会在 0.05 秒内返回到与哈希值相同的状态。

注意:2000 DWU 在 xlarge 资源中运行查询(最大内存分配)

在检查散列键的分布时,我发现 1.4 亿条记录存储在 60 个数据库的一个分布中。5000 万条其他记录相当均匀地分布在其他 59 个数据库中。默认值是使我的散列键不适合散列。

我的问题是,虽然带有统计信息的循环表在我与另一个表散列的同一字段上表现出色,但当我在 JOINS 上使用该键的循环时,相同的性能会保持不变吗?我还没有完全测试它,但正在寻找最好的方法。

统计信息对联接有帮助吗?我读过的一些文章说他们这样做,但是在考虑对分发密钥进行循环时,看看其他人是否对这种方法有更可靠的答案。我真的没有任何好的候选人不会像我上面的例子中的 1.4 亿那样导致数据倾斜。

4

1 回答 1

1

首先,在当前版本的 Azure SQL 数据仓库中,您应该始终为将在连接GROUP BY等中使用的列创建统计信息。忽略没有统计信息的时间,因为它们无关紧要。

一个好的散列键的标准之一是它均匀地分布数据。如果你没有一个好的候选人,那ROUND_ROBIN是另一种选择。要记住的ROUND_ROBIN是,您总是会移动数据,但有时这很好。这实际上取决于您的关键查询是什么。我的建议是针对他们进行优化。

对于您提供的示例,性能如此之快,以至于不值得花太多时间。你有一些更现实的问题吗?

Azure SQL 数据仓库会缓存,类似于 SQL Server,如此所述。

当您从门户提供仓库时,我使用 AdventureWorksDW 示例模拟了一个测试平台,并发现哈希表对于这些示例查询的性能明显更好(尽管偏差很大),但您的里程可能会有所不同(YMMV):

-- 603,980,000 rows
CREATE TABLE dbo.FactTable_rr
WITH ( 
    DISTRIBUTION = ROUND_ROBIN, 
    CLUSTERED COLUMNSTORE INDEX
)
AS
SELECT a.ProductKey AS [ProductID], a.CustomerKey AS [CustomerID]
FROM [dbo].[FactInternetSales] a
    CROSS JOIN ( SELECT TOP 1000 1 FROM [dbo].[FactInternetSales] ) b(c)
    CROSS JOIN ( SELECT TOP 10 1 FROM [dbo].[FactInternetSales] ) c(c)
GO


CREATE STATISTICS st_dbo_FactTable_rr_ProductID ON dbo.FactTable_rr ( ProductID ) WITH FULLSCAN;
CREATE STATISTICS st_dbo_FactTable_rr_CustomerID ON dbo.FactTable_rr ( CustomerID ) WITH FULLSCAN;
GO


CREATE TABLE dbo.FactTable_hh
WITH ( 
    DISTRIBUTION = HASH( [ProductID] ),
    CLUSTERED COLUMNSTORE INDEX
)
AS
SELECT *
FROM FactTable_rr
GO

CREATE STATISTICS st_dbo_FactTable_hh_ProductID ON dbo.FactTable_hh ( ProductID ) WITH FULLSCAN;
CREATE STATISTICS st_dbo_FactTable_hh_CustomerID ON dbo.FactTable_hh ( CustomerID ) WITH FULLSCAN;
GO



-- Find data skew for a distributed table
DBCC PDW_SHOWSPACEUSED('dbo.FactTable_rr');
DBCC PDW_SHOWSPACEUSED('dbo.FactTable_hh');
GO


--EXPLAIN
SELECT
   [ProductID],
   COUNT(DISTINCT [CustomerID]) AS [Unique Records]
FROM [dbo].[FactTable_rr]
GROUP BY [ProductID]
OPTION ( LABEL = 'rr' );


--EXPLAIN
SELECT
   [ProductID],
   COUNT(DISTINCT [CustomerID]) AS [Unique Records]
FROM [dbo].[FactTable_hh]
GROUP BY [ProductID]
OPTION ( LABEL = 'hh' );


-- Summary
SELECT [label], COUNT(*) records, CAST( AVG(total_elapsed_time) / 1000. AS DECIMAL(10,2) ) total_elapsed_time_s
FROM sys.dm_pdw_exec_requests 
WHERE [label] IS NOT NULL
  AND command Like 'select%'
GROUP BY [label];

我的结果,包含 6 亿行的表:

我的结果

如果我查看两个查询的两个 EXPLAIN 计划(rrhh),我会看到一个更简单的哈希表计划,没有数据移动。'rr' 计划包含一个SHUFFLE_MOVE重新分配分布式表的运算符。

于 2017-04-15T23:57:32.283 回答