为什么重用DataContext会对性能产生负面影响?

时间:2010-07-13 02:44:06

标签: c# sql-server linq-to-sql optimization datacontext

fair amount of research和一些errors之后,我修改了我的代码,以便每次查询数据库时都会创建一个新的DataContext或插入数据。并且经常查询数据库 - 对于每个处理的250k事务,在插入事务之前,将查询数据库以获取客户ID,部门ID和类别。

所以现在我正在尝试优化代码,因为它每秒只处理大约15个事务。我删除了一些无关的查询并添加了一些索引,并将其提高到30 /秒。然后我想,尽管每个人都说DataContext是轻量级的,但是每个事务需要花费4倍的时间来创建一个新的,所以我尝试重用DataContext。令我惊讶的是,我发现重复使用上下文会导致性能降低到每秒10个事务!

为什么会出现这种情况?是因为DataContext将实体缓存在内存中,并在查询数据库之前首先搜索其内存列表?因此,例如,如果我正在寻找名为“MCS”的客户的客户ID(主键),并且客户名称列上有聚簇索引,以便数据库查询速度快,则在内存中查找会慢一点吗?

创建/部署如此多的数据库连接是否会减慢速度,或者这只是另一种过早的优化?如果确实如此,是否有办法重用DataContext但是它为每个linq-to-sql查询执行实际的数据库查询?

4 个答案:

答案 0 :(得分:15)

这就是为什么重复使用DataContext不是最佳做法,来自MSDN DataContext documentation

  

DataContext是所有人的来源   映射到数据库的实体   连接。 跟踪您的变化   对所有检索到的实体和   维护一个“身份缓存”   保证检索实体   不止一次代表   使用相同的对象实例。

     

通常,DataContext实例是   旨在持续一个“单位   工作“但你的应用程序定义   那个词。 DataContext是   轻便且不贵   创建。典型的LINQ to SQL   应用程序创建DataContext   方法范围或实例   昙花一现的成员   代表一组相关的逻辑   数据库操作。

如果您为大量查询重复使用DataContext,您的性能会因几种可能原因而降低:

  1. 如果DataContext的内存中的身份缓存变得如此之大以至于必须开始写入页面文件,那么你的性能将受到HD的读取头速度的限制,并且实际上没有理由使用缓存。

  2. 内存中的身份对象越多,每次保存操作所需的时间就越长。

  3. 基本上你正在做的是违反DataContext类的UoW原则。

    打开数据库连接确实会产生一些与之相关的开销,但是长时间保持连接打开(这通常也意味着锁定表)不如快速打开和关闭它们更可取。

    MSDN中可能有或没有帮助您的另一个链接:

    How to: Reuse a Connection Between an ADO.NET Command and a DataContext (LINQ to SQL)

答案 1 :(得分:1)

即使使用聚簇索引,内存中查找也总是比数据库查询更快 - 除非在边缘情况下,例如386与Cray相比 - 即使您分解出与网络相关的延迟。

我猜测降级与DataContext对其跟踪的实体的处理有关:重用上下文会不断增加被跟踪实体的数量,而对SaveChanges的调用最终可能需要更多时间。

再次,这是一个猜测 - 但它是我开始寻找的地方。

答案 2 :(得分:1)

您必须对所有内容进行端到端的分析,并了解您的实际用时时间。

如果行宽,则聚簇索引不一定是最快的。最快的可能是覆盖非聚集索引,但这真的不是重点。

我希望如果你没有真正使用这些功能,那么为了获得更高的性能,你可能不得不抛弃一些框架。如果你正在使用这些功能 - 那就是你付出的代价......

答案 3 :(得分:1)

这里不完全是这样,但您是否考虑过某种应用程序级缓存来查找客户ID,部门ID和类别?从您的帖子中不清楚您的系统中存在多少这些实体,或查询获取它们涉及的内容。

但是,作为一个例子,如果您的系统中有一百万个类别,并且您需要按类别名称查找其ID,那么在内存中保留名称/ Id字典以便随时查找将节省您前往您处理的事务的数据库。这可以大大提高性能(这假设了一些事情,比如没有定期添加新的护理)。作为一般规则,与内存操作相比,往返数据库的往返费用很高。