本文属于【Azure Data Platform】系列。
接上文:【Azure Data Platform】Dedicated SQL Pool——导入性能测试(3)——Copy
首先,我们需要知道SQL DW是一个MPP的系统。关于导入,为了最大限度地提高负载性能,负载会话应利用 MPP 体系结构直接连接到计算。SQL DW的每个计算节点(compute node)通过DMS服务,借助HDFS bridge来访问存储上的数据。
这个过程,跟DWU有很大关系,如下图所示,每个DWU都有对应的reader和writer。 因为我们实验用的是parquet,所以在2000c下,有128个readers和240个writers。
每个reader自动读取 Azure 存储 BLOB 的每个文件的 512MB,自动读取 Azure Data Lake 存储上的 256MB。这里我们用的是ADLS,所以也就是256MB/reader, 也就是说一次性理论最大值是128*256 MB=27GB。
但是对于 Parquet 文件,每个压缩文件也只使用一个reader,因此为了获得最佳性能,文件数应大于或等于reader的总数。也就是说如果我们的文件有60个,最多也就使用60个reader,这样实际读取性能为60*256MB=15GB。
同时注意我这次使用的是largerc 的resource class,也就是22%的资源占用。
在导入Round_robin表时,可以看到下面的样子:
这就是数据移动服务DMS的每个HDFS桥段实现加载的方式。
为了最小化导入时间,很多不必要的操作应该避免,比如ShuffleMoveOperation操作,这种操作很耗时,可以通过使用round_robin来移除它。这也是为什么round_robin会更加快。
如果使用下面SQL 在导数时进行监控。
select type,pdw_node_id,sum(length) as file_size,sum(bytes_processed) as bytes_processed , count(*) as total_file_split from
sys.dm_pdw_dms_external_work where request_id ='XXXXXXX' group by type,pdw_node_id
可以看到类似如下的结果:
从结果中得到DMS的运行情况。file_size是这部分拆分后文件的大小。而bytes_processed是已处理的文件。
如果想知道当前的reader,writer有多少:
select type ,count(*) as cnt from [sys].[dm_pdw_dms_workers] where request_id='XXXXXXX' and step_index=5 group by type
细化分析:
select type,pdw_node_id,status,count(*) as threads,sum(bytes_processed/(1024*1024)) as size_mb ,
sum(rows_processed) as total_row ,avg(total_elapsed_time) as avg_elapsed_time from [sys].[dm_pdw_dms_workers]
where request_id ='XXXXXXX' and step_index=5 and type='WRITER' group by type,pdw_node_id,status;
;
为了方便期间,把SQL 整合成这样:
select ab.request_id, ab.step_index,ab.operation_type,ab.location_type,
ab.status,
ab.error_id,
ab.start_time,
ab.end_time,
ef.type as DMStype,
ef.status as DMSstatus,
ef.numthreads as DMSthreads,
ab.command, ef.sum_bytes_processed , ef.max_bytes_processed ,
ef.min_bytes_processed ,
ef.sum_rows_processed ,ef.min_rows_processed ,
ef.max_rows_processed ,
ef.sum_total_time,
ef.max_total_time,ef.min_total_time
from sys.dm_pdw_request_steps ab
inner join (
select b.request_id,b.step_index , b.type,status ,count(*) as numthreads, sum(cast(b.bytes_processed as bigint)) as sum_bytes_processed ,
max(b.bytes_processed) as max_bytes_processed ,
min(b.bytes_processed) as min_bytes_processed ,
sum(cast(b.rows_processed as bigint)) as sum_rows_processed , min(b.rows_processed) as min_rows_processed ,
max(b.rows_processed) as max_rows_processed ,
sum(cast(b.total_elapsed_time as bigint)) as sum_total_time,
max(b.total_elapsed_time) as max_total_time,
min(b.total_elapsed_time) as min_total_time
from sys.dm_pdw_dms_workers b
group by
b.request_id,b.step_index , b.type,b.status ) ef
on ab.request_id=ef.request_id and ab.step_index=ef.step_index
inner join (select request_id FROM sys.dm_pdw_exec_requests
where status not in ('Completed','Failed','Cancelled') and session_id <> session_id()) er
ON ab.request_id=er.request_id;
那么实际样子会是以下的情况:
从结果上可以看到很多运行信息,不过还是建议读者自行在自己环境下查看,毕竟我的实验还是有不少的局限性。