大表 (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) 上的插入性能非常慢的主要内容,如果未能解决你的问题,请参考以下文章

大表上的第一次查询调用速度非常慢

大表的mysql性能问题

MySQL 大表性能不佳

mysql 表很少,一个大表上的子查询执行缓慢

PostgreSQL大表的更新时间

Mysql + 大表 = 慢查询?