我有一个从多个套接字接收数据然后将数据写入数据库的应用程序。
我目前正在使用 EF 来执行此操作。我想知道如何让它更有效率。
我读到过批量插入速度更快,所以我每 500 次插入才将更改保存到数据库:
db.Logs_In.Add(tableItem);
if (logBufferCounter++ > 500)
{
db.SaveChanges();
logBufferCounter = 0;
}
现在我已经分析了应用程序,74% 的工作由函数完成:System.Data.Enitity.DbSet'1[System._Canon].Add
有没有更好的插入方式?也许将 tableItems 排队到一个列表中,然后将整个列表添加到数据库上下文中。
或者也许我看错了,我应该完全避免使用 EntityFramework 来实现这种更高性能的插入?目前它是我的应用程序中的瓶颈,如果我查看系统资源,SQL 似乎连眼皮都没动一下。
所以我的问题:
1:我将以何种方式在多个插入中实现最高效/最快的插入
2:如果 EF 可以接受,我该如何改进我的解决方案?
我使用的是 SQL Server 2012 企业版, 传入的数据是一个恒定的流,但是我可以缓冲它,如果这是更好的解决方案,然后执行批量插入。
[编辑]
进一步解释场景。我有一个在 concurrentQueue 上循环的线程,它使该队列中的项目出队。然而,由于数据库插入是瓶颈这一事实。队列中通常有数千个条目,因此如果还有一种异步或并行方式,我可能会使用多个线程来执行插入操作。
最佳答案
对于涉及大量插入的场景,我倾向于“单独缓冲”(内存中,或 redis 列表,或其他),然后作为批处理作业(可能每分钟,或每隔几分钟)读取列表和使用 SqlBulkCopy
尽可能有效地将数据放入数据库。为了解决这个问题,我使用了 ObjectReader.Create
fastmember的方法,它公开了一个 List<T>
(或任何 IEnumerable<T>
)作为 IDataReader
可以输入 SqlBulkCopy
, 公开 T
的属性作为数据阅读器中的逻辑列。然后,您需要做的就是填写 List<T>
来自缓冲区。
但是请注意,您需要考虑“出现问题”的情况;即,如果插入中途失败,您将如何处理缓冲区中的数据?这里的一种选择是执行 SqlBulkCopy
进入一个staging 表(相同的架构,但不是“实时”表),然后使用常规 INSERT
当您知道数据在数据库中时,一步复制数据 - 这使恢复更简单。
关于c# - 如何改进 Entity Framework 批量插入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24882766/