我有一个庞大的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中的所有记录加载到内存中。我不太确定最有效的方法。我目前的想法如下:
我的问题如下: 保存所有这些数据的内存效率最高的数据结构是什么?不需要随机访问。 LINQ-to-SQL是否应该用于执行验证?我知道它不是查询数据库的最佳表现方法。 我是否会对项目的这个组成部分做错了?
欢迎任何建议或建议!
答案 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中运行所有内容。