工作高峰时段的 Sql Server 批量插入

Posted

技术标签:

【中文标题】工作高峰时段的 Sql Server 批量插入【英文标题】:Sql Server Bulk Insert during peak operations hours 【发布时间】:2021-01-05 06:56:17 【问题描述】:

我在数据库中有一个表,该表通常非常频繁地同时查询,峰值接近每秒 100 次选择(根据分析数据推测)。表中的行数很快就会达到 2 亿条记录。对单个/单个行的持续更新,也继续执行。

此表中的数据是通过夜间作业填充的,故意在凌晨 1 点非高峰时间,以免影响性能。导入大小有时可以达到 100 万条记录。使用SqlBulkCopy,如下例。

var dt = new DataTable();
dt.Columns.Add("EmployeeID");
dt.Columns.Add("Name"); 

for (var i = 1; i < 1000000; i++)    
    dt.Rows.Add(i + 1, "Name " + i + 1);

using (var sqlBulk = new SqlBulkCopy(_connectionString))

    sqlBulk.DestinationTableName = "Employees";
    sqlBulk.WriteToServer(dt);

最近收到源数据系统的请求,两次抽数据,白天也抽一次,有效的让我们在高峰时段插入数据。

关于如何在不影响最终用户体验的性能的情况下执行 SqlClient.SqlBulkCopy 操作的任何建议。这种场景有可扩展的解决方案吗?现有行数增加,导入大小增加和最终用户群增加,但我仍然可以在一天中的任何时间继续执行如此庞大的数据抽取。

抱歉,没有太多具体的数据点可以分享,有点含糊。只是想了解其他人是如何做到这一点的,如果有人有这样的经历的话。

【问题讨论】:

您也许可以研究分区并将临时表切换到主表:brentozar.com/archive/2012/03/… 感谢@SteveFord。分区更适合您共享的报告示例。在我的情况下,日期范围不能真正成为分区。我的数据是用户通知。需要一起获取和服务最新的和最旧的。关于临时表的方式-您能详细说明一下吗?您的意思是我们首先将批量数据存放在临时表中,然后如何将其快速移动到主表而不影响传入的选择? 即使使用分区,您也可以同时获取最新和最旧的数据。该表的访问方式与其他任何表一样,只是分区表在物理上存储为单独的表。对表的任何查询都会从所有分区并行获取数据。暂存的想法是您加载到一个看起来像分区表的暂存表中并执行 switch 语句。这使得 staging table 成为 table 的一部分,这只是改变了元数据。 其他替代方案是尝试读取已提交快照隔离,特别是如果您的加载进程是写入数据库的唯一进程。使用此设置(在 DB 级别设置)读取永远不会阻止写入并且写入永远不会阻止读取。您可能需要增加 TempDB 的大小,但如果您仍然批量插入,则不一定。 【参考方案1】:

您可以小批量加载数据,这样您就不会产生大事务并消耗大量事务日志。在每批之后,您可以提交事务。您可以使用内部事务处理方法,将每个批次作为单独的事务处理。 Read more on transactions and bulkcopy

using (SqlBulkCopy bulkCopy = new SqlBulkCopy(
                       connectionString, SqlBulkCopyOptions.KeepIdentity |
                       SqlBulkCopyOptions.UseInternalTransaction))
            
                bulkCopy.BatchSize = 10000;
                bulkCopy.DestinationTableName =
                    "dbo.BulkCopyDemoMatchingColumns";

                // Write from the source to the destination.
                // This should fail with a duplicate key error
                // after some of the batches have been copied.
                try
                
                    bulkCopy.WriteToServer(reader);
                
                catch (Exception ex)
                
                    Console.WriteLine(ex.Message);
                
                finally
                
                    reader.Close();
                
            

此外,还有一些与批量复制相关的优化提示。您可以尝试在可能的情况下利用:Bulk Copy optimizations

【讨论】:

嘿@Venkataraman。谢谢。这也是我们在夜间工作中已经在做的事情。使用小批量插入。你的意思是在快速射击大量小批量,在高峰时段不会有太大影响? @techrookie,是的。小批量并经常提交它们,将避免内存压力和事务日志压力。我们之前尝试过小批量,这减少了主表的阻塞。

以上是关于工作高峰时段的 Sql Server 批量插入的主要内容,如果未能解决你的问题,请参考以下文章

sql server有批量插入和批量更新的sql语句吗

JPA SQL Server 批量插入

在 SQL Server CE 中批量插入

SQL Server 批量插入数据的两种方法 - 转

Myeclipse 如何用java 写sqlserver 的批量插入?

从 Excel / CSV 批量插入到 SQL Server