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

C# 为什么重用DataContext会对性能产生负面影响?,c#,sql-server,linq-to-sql,optimization,datacontext,C#,Sql Server,Linq To Sql,Optimization,Datacontext,经过一段和一段时间后,我修改了代码,以便在每次查询数据库或插入数据时创建一个新的DataContext。并且经常查询数据库—对于处理的25万笔交易中的每一笔,在插入交易之前,都会查询数据库以获取客户id、部门id和类别 现在我正试图优化代码,因为它每秒只处理大约15个事务。我删除了一些无关的查询,添加了一些索引,并将其设置为每秒30次。然后我发现,尽管每个人都说DataContext是轻量级的,但每次事务创建一个新的DataContext需要花费一定的成本,所以我尝试重用DataContext。

经过一段和一段时间后,我修改了代码,以便在每次查询数据库或插入数据时创建一个新的DataContext。并且经常查询数据库—对于处理的25万笔交易中的每一笔,在插入交易之前,都会查询数据库以获取客户id、部门id和类别

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

为什么会这样?这是因为DataContext将实体缓存在内存中,并在查询数据库之前首先搜索其内存中列表吗?例如,如果我正在查找名为“MCS”的客户的客户id(主键),并且客户名称列上有一个聚集索引,以便数据库查询速度较快,那么内存中的查找速度会较慢吗


创建/处理如此多的数据库连接是否真的会减慢速度,或者这只是又一次过早的优化?如果这是真的,有没有一种方法可以重用DataContext,但让它为每个linq到sql查询执行实际的数据库查询?

即使使用聚集索引,内存中的查找也总是比数据库查询快——除了在边缘情况下,比如386对Cray——即使考虑到与网络相关的延迟

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


同样,这是一个猜测——但这正是我要开始寻找的地方。

以下是重新使用DataContext不是最佳实践的原因:

DataContext是所有数据的源 在数据库上映射的实体 连接它跟踪您所做的更改 对所有检索到的实体和 维护一个“身份缓存”,该缓存 保证检索到的实体 多个时间由 使用相同的对象实例。

通常,DataContext实例是 设计寿命为一个“单位 工作“无论应用程序如何定义 这个术语。数据上下文是 重量轻,使用成本不高 创造。典型的LINQ到SQL 应用程序创建数据上下文 方法范围内的实例或作为 短期类的成员 表示一组逻辑上相关的 数据库操作

如果您使用DataContext进行大量查询,您的性能将因以下几个可能的原因而降低:

  • 如果DataContext的内存中标识缓存变得如此之大,以至于它必须开始写入页面文件,那么您的性能将与HD的读取头速度相关联,实际上根本没有理由使用缓存

  • 内存中的标识对象越多,每次保存操作所需的时间就越长

  • 实际上,您所做的违反了DataContext类的UoW原则

    打开数据库连接确实会带来一些相关的开销,但将连接保持长时间打开(通常也意味着锁定表)不如快速打开和关闭它们

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


    你必须端到端地分析每件事,看看你的时间真正花在了哪里

    如果行很宽,则聚集索引不一定是最快的。最快的可能是一个覆盖非聚集索引,但这真的离题了


    我希望,为了获得更高的性能,如果您没有真正使用这些功能,您可能不得不放弃一些框架。如果您正在使用这些功能,那么,这就是您要支付的费用……

    这一点并不确切,但您是否考虑过某种应用程序级缓存来查找客户id、部门id和类别?从您的帖子中不清楚您的系统中存在多少这样的实体,也不清楚查询获取这些实体涉及到什么

    但是,例如,如果您的系统中有一百万个类别,并且需要按类别名称查找它们的Id,则在内存中保留一个名称/Id字典以便随时查找,这将为您处理的事务节省访问数据库的时间。这可以极大地提高性能(这假设了一些事情,比如没有定期添加新的职业)。一般来说,与内存中的操作相比,到数据库的往返开销很大