插入表 Exec SP 性能不佳

Rya*_*ati 5 performance sql-server insert sql-server-2016 exec query-performance

我正在开发一个数据仓库。我们每晚刷新的一个临时表有大约 1000 万行。我们正在使用自定义构建的 ETL 工具,我无法对其进行太多更改。该工具像这样加载这个临时表:

truncate stage_table;
insert into stage_table with (tablockx) (column1, column2, etc...)
exec load_stage_table @batch_id = @batch_input
Run Code Online (Sandbox Code Playgroud)

的内容load_stage_table有一些设置和选择语句。我无法分享确切的代码,但这是一个基本示例。

create table load_stage_table
(
     @batch_id varchar(max) = null
)
as 

-- <update batch_id in batch_table>

-- collect data

select
    column1 = table1.column1,
    column2 = table2.column2,
    ...
from table1
join table2
    on table2.id = table1.table2_id
-- many more similar joins
Run Code Online (Sandbox Code Playgroud)

问题是,当我按照 ETL 工具运行的方式运行存储过程时,运行时间几乎是 30 分钟。但是,如果我修改存储过程以在内部包含插入语句,则只需 1 分钟。

    create table load_stage_table
(
     @batch_id varchar(max) = null
)
as 

-- <update batch_id in batch_table>

-- collect data
insert into stage_table with (tablockx) (column1, column2, etc...)
select
    column1 = table1.column1,
    column2 = table2.column2,
    ...
from table1
join table2
    on table2.id = table1.table2_id
-- many more similar joins
Run Code Online (Sandbox Code Playgroud)

在以两种方式运行几次并检查执行计划后,似乎当插入在存储过程之外时没有使用并行性。

从存储过程之外的返回加载表是否会阻止并行?或者这是否表明 select 语句需要一些查询调整?

Sol*_*zky 9

INSERT...EXEC 可能会禁止并行性,但我非常怀疑这是这里的主要问题。问题是它的INSERT...EXEC工作方式与INSERT...SELECT. 将查询的结果(即SELECT语句或OUTPUT子句)插入表中时,结果将流式传输到表中。如果您正在观看row_countused_page_countsys.dm_db_partition_stats,您会发现它们随着INSERT...SELECT开始而立即增加。

但是,当插入EXEC(通常是存储过程,但也可能是动态 SQL)的结果时,子流程/存储过程需要在将任何内容插入表之前完全完成(是的,我刚刚测试了这个)。如果您正在观看row_countused_page_countsys.dm_db_partition_stats,您会发现他们在0开始后停留(或他们开始的任何地方)很一段时间INSERT...EXEC。当存储过程返回数百万行时,这不是成功的秘诀,因为这些结果需要在插入表之前存储在某处。