大表 (EF) 上的插入性能非常慢
Posted
技术标签:
【中文标题】大表 (EF) 上的插入性能非常慢【英文标题】:Very slow insert performance on large table (EF) 【发布时间】:2016-05-24 09:50:06 【问题描述】:我们的一个系统有一个每天接收大约 20k 插入的表 - 它目前包含大约 1000 万行。我们刚刚推出了系统升级,现在我在插入此表时遇到了一些令人震惊的缓慢性能(30-40 秒的跟踪)。 Inserts 一次只能插入一行。实体框架正在生成以下 SQL:
declare @generated_keys table([ID] uniqueidentifier)
insert [dbo].[Table]([Col1], Col2], etc)
output inserted.[ID] into @generated_keys values (@0, @1, etc)
select t.[ID] from @generated_keys as g join [dbo].[Table] as t on g.[ID] = t.[ID] where @@ROWCOUNT > 0
没有什么不寻常的——至少在我看来。
该表有 12 个 FK。由于实体表示基于时间的事件,因此聚集索引位于 DateCreated
列上。还有 8 个非聚集索引,包含各种列。 ID
列是 PK,具有唯一的非聚集索引。
作为说明,我注意到,由于遗漏,ID
列使用newid()
而不是newsequentialid()
。
实际的执行计划包括以下主要部分:
7x 3% - FK 表上的聚集索引查找
1x 8% - 表格插入 (@generated_keys)
1x 74% - 聚集索引插入,1 个实际行,0.09 成本
我真的很想知道这件事的真相,但我现在很难过。有什么建议吗?
【问题讨论】:
你试过放弃 ClusteredIndex 吗? 它已经到位,因为该表上的几乎所有选择操作都按日期顺序返回数据。此外,鉴于插入是按日期顺序排列的,在我看来,此列上的聚集索引是有意义的,而不是使用 PK 列(唯一标识符)。 运行缓慢的插入是否一致,或者您是否有这么多运行速度很快,然后一个需要时间? 如你所说。系列/批次中的第一个查询可能需要一段时间,但后续运行会很快完成(以我一直期望的速度)。 似乎不是查询本身是问题,而是连接管理/模型构建。其中哪一个我真的不能说,但我假设是后者,因为模型看起来很复杂。 【参考方案1】:正如您所注意到的,SaveChange 为每个记录插入进行数据库往返。因此,如果您每天添加 20k 条记录,则会执行 20k 次数据库往返。
修改和改进索引几乎没有什么区别,因为真正的问题是数据库往返次数!
要修复性能,您必须使用允许执行批量插入的库
支持它的三个专业库:
Entity Framework Extensions (推荐并支持一切) EntityFramework.BulkInsert (不支持,使用简单场景) EntityFramework.Utilities (不支持,使用非常简单的场景)您可以在此处了解有关这三个库的更多信息: Entity Framework Bulk Insert Library Reviews & Comparisons
免责声明:我是项目的所有者Entity Framework Extensions
【讨论】:
批量插入不是问题,那些 20k 插入发生在 24 小时的时间跨度内。保存它们以进行批量插入不是一种选择。以上是关于大表 (EF) 上的插入性能非常慢的主要内容,如果未能解决你的问题,请参考以下文章