【问题标题】:Can the performance of DbLinq's object tracking be improved?DbLinq 的对象跟踪性能能提高吗?
【发布时间】:2012-06-19 19:22:49
【问题描述】:

我有一个通过 DbLinq 连接到 MySQL 数据库的 ASP.NET MVC2 站点。网站上会定期执行一组特定的操作,其中包括遍历几个表中的一组特定记录并更新它们,以及在其他一些表中添加一些新记录。

我一直在用一组中等规模的数据进行测试。在我现在的特定测试集中,在更新时它最终会插入 44 条新行并更新 81 条其他行。但是我对 SubmitChanges() 的调用最终花费了很长时间 - 大约 3-4 分钟,这似乎需要很长时间才能推动(我认为是)对数据库进行相对少量的更改。

我最终做了一些简单的分析,我发现问题似乎不在于在数据库上执行查询,甚至不在于构建查询。大多数时间似乎都被 UpdateEntity 内部对 AllTrackedEntities.ContainsReference() 的调用占用了。

为了给出一些实际的数字,我最近的一次测试运行:

  • SubmitChangesImpl 中的时间:204884 毫秒
    • UpdateEntity 中的时间:200908 毫秒
      • ContainsReference 中的时间:148173 毫秒
      • QueryBuilder.GetUpdateQuery 中的时间:685 毫秒
      • QueryRunner 中的时间。更新:28 毫秒
      • UpdateReferencedObjects 中的时间:49958 毫秒

如您所见,构建和运行 SQL 查询与检查是否存在对我们正在更新的实体的引用相比相形见绌(如果没有引用,则插入实体,尽管在这种情况下所有更新的实体都存在)。虽然我理解为什么会发生这种情况,为了维护数据完整性等等,但这会破坏这些定期更新操作的性能。

我查看了将 ObjectTrackingEnabled 设置为 false,但这使得 DataContext 是只读的,这对我没有用 - 我的问题特别是更新的性能。

有什么可以提高更新性能的方法吗?就尝试在一次提交中推送 40-50 次插入和 80 多次更新而言,我是否以不太理想的方式使用 DbLinq?如果是这样,有没有更好的方法来解决这个问题?

【问题讨论】:

  • 你的逻辑一定会妨碍你,显示一些代码 - 或者至少给出一个简洁的例子来重现你遇到的问题。我构建了复杂的输入表单,最终使用 EF 4.1 发送大约 18 条记录以添加到 mysql 数据库中,如果那样的话,大约需要 5 - 10 秒。
  • 您是否长期使用相同的dataContext,即读取一些行,更新/添加一些行,提交更改,然后使用相同的dataContext重复?
  • @hatchet - 我知道这是针对 OP 的,但在我的存储库中,每次进行更改时我都会保存更改,并始终使用相同的 dataContext。如果他多次打开和关闭连接,这可能会增加时间。但是,在我看来,发生了某种n! 操作。
  • 我对 linq to Sql 的理解是,实体一旦物化,就保留在上下文的内部缓存中。对于长期存在的上下文,这可能会积累大量可能陈旧的数据,并为其内部更改跟踪带来更多工作。 DataContext 的目的是短暂的......使用它并折腾它。它们的建造成本很低。
  • @hatchet 是绝对正确的,我的问题在我的 DataContext 上的生命周期太长了。我曾认为,由于所有操作都构成一个逻辑事务,我最好使用一个 DataContext,最后使用一个 SubmitChanges。我放入了许多 SubmitChanges 进行测试,然后很明显 - 每个后续的 SubmitChanges 都比前一个花费更长的时间,即使它做的“工作”比以前少。将其分解为单独的、短暂的 DataContext 就可以了。如果您想将其添加为答案,我会尽快接受。

标签: c# mysql dblinq


【解决方案1】:

如果您使用长期存在的 DataContext,在其中读取数据、修改数据、提交更改,然后重复使用相同的 DataContext 对象,这可能会对性能产生负面影响。一旦 DataContext 实体化了一个实体,它就会在 DataContext 的整个生命周期内将其保留在内部,作为其对象跟踪的一部分。随着时间的推移,这个内部缓存会变得很大,在某些情况下,它实际上会成为数据库大部分的内存缓存。这会减慢速度,并在 SubmitChanges 期间为 DataContext 带来更多工作。

DataContext 是短暂的。它的生命周期应该是一个工作单元。创建它,将其用于某事,然后处置它。

这里有更多细节:

Why would reusing a DataContext have a negative performance impact?

这是由接近产品的人提供的:

http://blogs.msdn.com/b/dinesh.kulkarni/archive/2008/04/27/lifetime-of-a-linq-to-sql-datacontext.aspx

长期使用:DataContext 本身不会覆盖对象 一旦您通过查询检索它们。所以随着时间的推移, 如果经常更改检索到的对象,它们可能会变得陈旧。

SubmitChanges() 之后的生活:DataContext 可以在之后使用 SubmitChanges() 但必须小心。 SubmitChanges() 完成所有 找出你对 对象图。它为您订购 CUD 操作并提供 在每个更改的粒度上进行乐观并发检查 对象。

【讨论】:

    猜你喜欢
    • 2014-02-02
    • 2020-11-03
    • 2012-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-19
    • 1970-01-01
    相关资源
    最近更新 更多