首先,在当前版本的 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 计划(rr,hh),我会看到一个更简单的哈希表计划,没有数据移动。'rr' 计划包含一个SHUFFLE_MOVE
重新分配分布式表的运算符。