使用 UNION 增强来自多个表的插入查询的性能

Posted

技术标签:

【中文标题】使用 UNION 增强来自多个表的插入查询的性能【英文标题】:Enhancing the performance of insert query from multiple tables using UNION 【发布时间】:2019-02-09 02:59:52 【问题描述】:

我想一次将多个表插入到 1 个表中。

在此之前,我尝试合并所有表并从中创建一个新表,但这需要几个小时。

select * from tables_1_1
union
select * from tables_1_2
union
select * from tables_1_3
union
select * from tables_2_1
...
until
tables_35_3

我想,插入也许是解决方案,还是有更好的方法来做到这一点?

【问题讨论】:

看这里:***.com/questions/49916545/… @AlexanderVolok 它具有相同的性能。 OP 要求提高查询性能 @Hadi,这个想法是使用SELECT INTO .. FROM .. UNION ALL 指向 BULK INSERT。 SQL Server 中没有更快的合并表的方法。如果它仍然很慢,那么 DBA 和 OS 管理员将研究 db 的存储和恢复模型的性能 @Hadi,反之亦然,如果服务器有很多内核,并且它是 SQL Server 2014+ 和兼容级别 110+,表加载通过 SELECT INTO benefits 从并行性。 sqlperformance.com/2013/08/t-sql-queries/parallel-select-into 我担心基础索引的大小与所有这些表的总和相当:) 【参考方案1】:

我认为你的工作应该考虑两个因素:

    硬件和服务器规格 数据大小

如果您正在使用的机器规格不是很好并且您有大量数据,那么分发INSERT 操作(多次插入)将提高性能,因为它不会像@987654328 那样消耗内存@ 手术。 如果数据大小可以接受并且可以由 SQL Server 分配的内存处理,那么您应该使用带有 SELECT INTO 查询的公用表表达式:

WITH CTE_1 as (SELECT * FROM TABLE_1 
               UNION ALL
               SELECT * FROM TABLE_2
               UNION ALL
               SELECT * FROM TABLE_3)
 SELECT * 
 INTo New_Table
 FROM CTE_1

另请注意the difference between UNION and UNION ALL operations:

UNION 语句有效地对结果集执行 SELECT DISTINCT。如果您知道返回的所有记录在您的联合中都是唯一的,请改用 UNION ALL,它会提供更快的结果。还要尽量避免使用INSERT INTO,而是使用SELECT INTO,因为it is minimally logged assuming proper trace flags are set。

还有一点要提,(我没有测试过这种方法,但也许它应该会提供更好的性能 - 并且它可能会导致巨大的索引大小)您还应该尝试创建一个 indexed view遍历所有表(你提到的UNION查询),然后执行查询,例如:

SELECT * INTO ...  FROM vw_Unified

更新 1

如果您熟悉 SSIS,执行数据导入过程可能会在使用 SSIS 时提供更好的性能:

Data Import Performance Comparison T-SQL vs SSIS for large import SSIS for table-to-table inserts vs. (SQL only) INSERT INTO () SELECT FROM approach Implementing Foreach Looping Logic in SSIS

【讨论】:

【参考方案2】:

@OP,正如我在 cmets 中提到的,考虑检查这个线程:Fastest options for merging two tables in SQL Server

需要强调的几点:

简单或批量记录恢复和SELECT INTO .. FROM .. UNION ALL 导致批量插入没有争用 如果 SQL Server 2014+,考虑设置兼容级别 110 或更高,这将在数据加载期间启用并行性 如果 SQL Server 2017 和最终表将变得非常大,请考虑在最快的存储上创建一个单独的文件组并在此文件组上创建表:SELECT * INTO Temp ON [NewFilegroup] FROM Table1。新文件组中的文件数最好等于内核数 不要使用UNION,使用UNION ALL,否则SQL Server 必须对所有这105 个表的数据进行重复数据删除

不同存储上的数据和日志文件,因此它们不会相互干扰

自担风险:如果加载速度超过可能的风险,请考虑到ALTER DATABASE dbname SET DELAYED_DURABILITY = ALLOWED;并开始加载与DELAYED_DURABILITY = ON的事务

一般免责声明:这篇文章几乎基于个人观点


参考文献:

https://www.sqlservergeeks.com/select-into-on-filegroup/ https://www.sqlshack.com/use-parallel-insert-sql-server-2016-improve-query-performance/ https://dba.stackexchange.com/questions/12818/why-select-into-targettable-from-sourcetable-is-faster-than-insert-into-ta

【讨论】:

我们的讨论导致我们都发布了答案。 :)

以上是关于使用 UNION 增强来自多个表的插入查询的性能的主要内容,如果未能解决你的问题,请参考以下文章

缩短并优化多个表的查询

提高 PostgresSQL 聚合查询性能

hive UNION和子查询

sql 用union合并合并查询结果

如何管理跨多个表的大型数据集? UNION 与大表?

SQL高级查询基础