Azure 数据仓库生成串行更快的查询
Azure Data Warehouse Generate serial faster query
环境是 Azure DW
我有一个像下面这样的原始 table;
ID Start End Action date
1 10 15 Processed 25-10-2019
2 55 105 In-Progress 21-10-2019
.....
我需要 expand/transform 开始和结束列,以便它们成为序列号;
SN Action date
10 Processed 25-10-2019
11 Processed 25-10-2019
12 Processed 25-10-2019
13 Processed 25-10-2019
14 Processed 25-10-2019
.....
Azure 数据仓库不支持递归 CTE 或游标。所以,尝试了一个 while 循环,
create table #temp_output (SerialNumber int not null, startSerialNumber int not null, endSerialNumber int not null);
insert into #temp_output select startSerialNumber, startSerialNumber, endSerialNumber from dbo.raw
declare @rowcount int, @cnt int, @start int, @end int
set @cnt = 1
set @rowcount = (select count(*) from dbo.raw)
while @cnt <= @rowcount
begin
select top (@cnt) @start = startSerialNumber from dbo.raw
select top (@cnt) @end = endSerialNumber from dbo.raw
while @start <= @end
begin
insert #temp_output
select max(SerialNumber) + 1,
startSerialNumber,
endSerialNumber
from #temp_output group by startSerialNumber, endSerialNumber having max(SerialNumber) < endSerialNumber
set @start = @start + 1
end
set @cnt = @cnt + 1
end
select SerialNumber, startSerialNumber, endSerialNumber from #temp_output_delta order by SerialNumber
然而,这需要很长时间(6 小时,当我取消查询时),因为原始 table 有 5000 万行。
需要更好的方法。
更新信息 2019 年 10 月 31 日
源 table 的分布是散列。 500 元。
源代码中有 6000 万行 table。
开始和结束之间的平均差异 3000。
起步也可以是200万。
main table 上没有索引。
列数 15
原始 table.
上的聚集列存储索引
您的样本不完整,但您不需要循环。您可以使用 BETWEEN
将其加入计数 table
如果你有一个计数 table(这是一个 table,里面只有从 1 到... 100 万的数字)
SELECT T.TallyNumber As SN, E.Action, E.Date
FROM YourTable E
INNER JOIN TallyTable As T
ON T.TallyNumber BETWEEN E.Start AND E.End
由于您要将其加载到新的 table,因此您应该使用 CTAS
CREATE TABLE [dbo].[NewTable]
WITH
(
DISTRIBUTION = HASH([Start])
,CLUSTERED COLUMNSTORE INDEX
)
AS
SELECT T.TallyNumber As SN, E.Action, E.Date
FROM YourTable E
INNER JOIN TallyTable As T
ON T.TallyNumber BETWEEN E.[Start] AND E.[End];
注意 DISTRIBUTION
周围有很多设计。您需要正确执行此操作以提高性能。上面的语句只是一个例子。您可能应该使用不同的散列。
您需要获得两个源 table 的分布以及目标 table 的分布才能获得良好的性能。
环境是 Azure DW 我有一个像下面这样的原始 table;
ID Start End Action date
1 10 15 Processed 25-10-2019
2 55 105 In-Progress 21-10-2019
.....
我需要 expand/transform 开始和结束列,以便它们成为序列号;
SN Action date
10 Processed 25-10-2019
11 Processed 25-10-2019
12 Processed 25-10-2019
13 Processed 25-10-2019
14 Processed 25-10-2019
.....
Azure 数据仓库不支持递归 CTE 或游标。所以,尝试了一个 while 循环,
create table #temp_output (SerialNumber int not null, startSerialNumber int not null, endSerialNumber int not null);
insert into #temp_output select startSerialNumber, startSerialNumber, endSerialNumber from dbo.raw
declare @rowcount int, @cnt int, @start int, @end int
set @cnt = 1
set @rowcount = (select count(*) from dbo.raw)
while @cnt <= @rowcount
begin
select top (@cnt) @start = startSerialNumber from dbo.raw
select top (@cnt) @end = endSerialNumber from dbo.raw
while @start <= @end
begin
insert #temp_output
select max(SerialNumber) + 1,
startSerialNumber,
endSerialNumber
from #temp_output group by startSerialNumber, endSerialNumber having max(SerialNumber) < endSerialNumber
set @start = @start + 1
end
set @cnt = @cnt + 1
end
select SerialNumber, startSerialNumber, endSerialNumber from #temp_output_delta order by SerialNumber
然而,这需要很长时间(6 小时,当我取消查询时),因为原始 table 有 5000 万行。
需要更好的方法。
更新信息 2019 年 10 月 31 日
源 table 的分布是散列。 500 元。 源代码中有 6000 万行 table。 开始和结束之间的平均差异 3000。 起步也可以是200万。 main table 上没有索引。 列数 15 原始 table.
上的聚集列存储索引您的样本不完整,但您不需要循环。您可以使用 BETWEEN
如果你有一个计数 table(这是一个 table,里面只有从 1 到... 100 万的数字)
SELECT T.TallyNumber As SN, E.Action, E.Date
FROM YourTable E
INNER JOIN TallyTable As T
ON T.TallyNumber BETWEEN E.Start AND E.End
由于您要将其加载到新的 table,因此您应该使用 CTAS
CREATE TABLE [dbo].[NewTable]
WITH
(
DISTRIBUTION = HASH([Start])
,CLUSTERED COLUMNSTORE INDEX
)
AS
SELECT T.TallyNumber As SN, E.Action, E.Date
FROM YourTable E
INNER JOIN TallyTable As T
ON T.TallyNumber BETWEEN E.[Start] AND E.[End];
注意 DISTRIBUTION
周围有很多设计。您需要正确执行此操作以提高性能。上面的语句只是一个例子。您可能应该使用不同的散列。
您需要获得两个源 table 的分布以及目标 table 的分布才能获得良好的性能。