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 语句需要一些查询调整?
INSERT...EXEC 可能会禁止并行性,但我非常怀疑这是这里的主要问题。问题是它的INSERT...EXEC工作方式与INSERT...SELECT. 将查询的结果(即SELECT语句或OUTPUT子句)插入表中时,结果将流式传输到表中。如果您正在观看row_count和used_page_count从sys.dm_db_partition_stats,您会发现它们随着INSERT...SELECT开始而立即增加。
但是,当插入EXEC(通常是存储过程,但也可能是动态 SQL)的结果时,子流程/存储过程需要在将任何内容插入表之前完全完成(是的,我刚刚测试了这个)。如果您正在观看row_count和used_page_count从sys.dm_db_partition_stats,您会发现他们在0开始后停留(或他们开始的任何地方)很长一段时间INSERT...EXEC。当存储过程返回数百万行时,这不是成功的秘诀,因为这些结果需要在插入表之前存储在某处。
| 归档时间: |
|
| 查看次数: |
1593 次 |
| 最近记录: |