C# 使用 SQL Server BulkCopy 进行插入。有办法更新吗

问题描述 投票:0回答:1

背景:许多(数百个)远程资产通过 UDP 数据包从多个数据系统将数据发送到一个域,在该域中数据包被解析并加载到

System.Data.DataTable
中。每个数据点都是一个单独的
System.Data.DataRow

平均每天我们有 29 亿个数据点。所以有很多数据。有一个“实时”表,仅包含最新版本的数据。该表被分区为远程资产和数据系统上的不同数据库文件。

此外,远程资产分布在多台 SQL Server 计算机之间。通过表死锁进一步分散数据库和 UDP 到达问题。

一旦到达数据被解析并加载到 C# 中,

DataTable
,该远程资产/数据系统的现有数据将被删除,并且
BulkCopy
用于插入 C# 数据表中的行。这可行,但是?

我的问题:有没有办法更新而不是暴力删除/插入?我查看了链接 Using SQLBuilCopy to Insert DataC# Bulk Insert... 但我现在几乎正在做一个临时表。

如果我每次都创建一个

#temp
表,那么就会产生开销。然后我还是要把数据取到实时表中,然后删除
#temp
表。

我查看了

SqlDataAdapter
,但这更多的是为了更新现有数据,而且可能是少量的。

任何想法都会有帮助。

其他背景:我可以看到 SQL Server 的性能随着时间的推移而下降,尽管这应该是一个问题。另外,我必须经常对表进行重新分区,因为性能下降得很厉害(8 小时内出现 10,000 次超时或死锁等)。

c# sql-server t-sql sqlbulkcopy
1个回答
0
投票

您可能会考虑一种更复杂的方法,包括使用临时表与 MERGE 语句相结合来更新实时表。 MERGE 语句可以在单个操作中处理插入和更新,这针对高性能进行了优化,并避免了连续创建和删除临时表的开销。

您可以尝试以下方法:

  1. 创建临时表:该表将临时保存传入的数据。
  2. 使用 BulkCopy 将数据加载到临时表中:这利用了 SqlBulkCopy 的性能优势。
  3. 使用 MERGE 语句更新实时表:这可以有效地处理现有行的更新和新行的插入。
  4. 清理暂存台。

这是 SQL 中的示例合并语句:

string mergeSql = @"
MERGE INTO RealTimeTable AS target
USING StagingTable AS source
ON (target.AssetId = source.AssetId AND target.DataSystemId =   source.DataSystemId AND target.Timestamp = source.Timestamp)
WHEN MATCHED THEN 
UPDATE SET
    target.DataPointValue = source.DataPointValue,
    -- other column updates
WHEN NOT MATCHED BY TARGET THEN
INSERT (
    AssetId,
    DataSystemId,
    DataPointValue,
    Timestamp
    -- other columns
) VALUES (
    source.AssetId,
    source.DataSystemId,
    source.DataPointValue,
    source.Timestamp
    -- other columns
)
WHEN NOT MATCHED BY SOURCE THEN
DELETE;

TRUNCATE TABLE StagingTable; -- Clear the staging table after processing
";

using (SqlCommand mergeCommand = new SqlCommand(mergeSql, connection))
{
mergeCommand.ExecuteNonQuery();
}
© www.soinside.com 2019 - 2024. All rights reserved.