带有验证和插入/更新的大量数据加载(无法插入)

时间:2013-10-11 15:24:01

标签: c# sql-server linq-to-sql csv data-structures

我有一个庞大的CSV文件,我每周一次,只包含不到500万条记录。这些记录需要添加到我的SQL数据库(MS SQL Server)或更新,具体取决于它们是否已存在。我考虑过执行Bulk Upsert,但问题是我无法直接更新记录。这就是[对象的重要组成部分]的样子:

PatientRecord-
  int MRN; //primary key
  string first_name;
  string last_name;
  int? updated_mrn; 
  int? pat_id; //filtered unclustered unique index

当需要将记录添加到系统时,我们需要首先检查MRN是否已存在且其余数据是否匹配。如果是,则跳过记录,否则将其添加到List<PatientRecord>个例外。如果未找到MRN,我们需要检查pat_id是否已存在。如果是这样,则新MRN将添加对象的updated_mrn组件(并在db中更新),否则将创建新记录。问题是这需要永远。我的应用程序使用LINQ to SQL进行几乎所有其他数据库事务,但这不是处理每周加载/更新的最佳方法。我考虑过执行一些SQL Bulk操作来执行此操作,但之后我需要将CSV中的所有记录加载到内存中。我不太确定最有效的方法。我目前的想法如下:

  1. 将CSV数据加载到内存
  2. 将对象与数据库进行比较(使用Linq-to-sql)
  3. 如果发现 - 从结构中移除并放置在异常结构或更新结构中
  4. 批量插入非例外/更新
  5. 异常结构的批量更新
  6. 生成例外文件以供人工审核
  7. 我的问题如下: 保存所有这些数据的内存效率最高的数据结构是什么?不需要随机访问。 LINQ-to-SQL是否应该用于执行验证?我知道它不是查询数据库的最佳表现方法。 我是否会对项目的这个组成部分做错了?

    欢迎任何建议或建议!

3 个答案:

答案 0 :(得分:1)

如果您熟悉SSIS和TSQL,则以下内容应该非常简单且易于维护。 首先,创建一个ssis包以将原始数据加载到sql server表中。如果已知MRN对于每个文件是唯一的,则可以相应地索引这个新的“RAW”表。

其次,创建一个存储过程以{RA}数据Merge到生产表。合并将在单个操作中执行插入,更新或删除。

最后,您可以将它全部包装在SQL Server代理作业中。

我希望这会有所帮助......

答案 1 :(得分:1)

我会在C#中使用SqlBulkCopy

1 /使用SqlBulkCopy将CSV数据加载到登台表

2 /将登台表与数据库进行比较(使用Linq-to-sql或任何其他SQL代码)

3 /如果发现 - 从结构中移除并放置在异常结构或更新结构中

4 / Sql批量复制批量插入非例外/更新

您不应该将Linq-2-Sql用于插入,因为它将逐个执行(L2S中没有批量插入)

答案 2 :(得分:1)

现有答案很好,但我要补充一点:如果你在大批量中执行选择和DML,你可以在应用程序中保持大量逻辑而不会出现问题。始终向数据库发送少量,大查询。这节省了以下几个地方:往返时间​​,网络带宽,每个交易成本,每批次成本和每个报表成本。它还为优化器提供了执行批量操作的机会。对1M行进行排序比对1000x1000行进行排序要快得多。总的来说,这些可以弥补数量级的加速。

SQL Server没有批量更新或合并,但您可以批量插入到临时表中,然后一次执行一次合并/更新。

重点是:只要您使用少量且笨重的操作,您就可以做任何您想做的事情。您不需要在T-SQL中运行所有内容。