在fairamountofresearch和一些errors之后,我修改了代码,以便在每次查询数据库或插入数据时创建一个新的DataContext,并且频繁地查询数据库-对于所处理的250 k个事务中的每一个,在插入事务之前查询数据库以获得客户ID、部门ID和类别。
所以现在我尝试优化代码,因为它每秒只处理大约15个事务。我删除了一些无关的查询,添加了一些索引,并将其提高到30个/秒。然后我意识到,即使每个人都说DataContext是轻量级的,但每个事务创建4次新的DataContext也需要一些成本,所以我尝试重用DataContext。我发现,令我非常惊讶的是,重用上下文导致性能下降到每秒10个事务!
为什么会出现这种情况?是因为DataContext将实体缓存在内存中,并在查询数据库之前首先搜索其内存中的列表吗?因此,例如,如果我正在查找名为'MCS'的客户的客户ID(主键),而客户名称列上有一个聚集索引,因此数据库查询速度较快,内存中的查找速度就会较慢?
创建/处理如此多的数据库连接是否真的会减慢速度,或者这只是另一个过早的优化?如果是这样,是否有一种方法可以重用DataContext,但让它为每个linq-to-sql查询执行实际的数据库查询?
4条答案
按热度按时间kmb7vmvb1#
以下是MSDN DataContext documentation中重用DataContext不是最佳实践的原因:
DataContext是通过数据库连接Map的所有实体的源。它跟踪您对所有检索到的实体所做的更改,并维护一个“标识缓存”,以保证使用同一对象示例表示多次检索到的实体。
通常,DataContext示例设计为持续一个“工作单元”,而不管您的应用程序如何定义该术语。DataContext是轻量级的,并且创建成本不高。典型的LINQ to SQL应用程序在方法范围内创建DataContext示例,或者将其创建为表示相关数据库操作的逻辑集的短期类的成员。
如果您要为大量查询重用DataContext,则性能会由于以下几个可能的原因而降低:
1.如果DataContext的内存中标识缓存变得如此之大,以至于它必须开始写入页面文件,那么您的性能将与HD的读取头速度绑定,实际上根本没有理由使用缓存。
1.内存中的身份对象越多,每个保存操作所需的时间就越长。
您所做的实际上违反了DataContext类的UoW原则。
打开数据库连接确实会产生一些相关的开销,但是长时间保持连接打开(这通常也意味着锁定表)不如快速打开和关闭连接好。
另一个链接可能对您有帮助,也可能没有帮助:
How to: Reuse a Connection Between an ADO.NET Command and a DataContext (LINQ to SQL)
vq8itlhq2#
即使使用聚集索引,内存中的查找也总是比数据库查询快--除了一些边缘情况,比如386与Cray的比较--即使不考虑与网络相关的延迟。
我猜这种降级与DataContext对其跟踪的实体的处理有关:重用上下文将不断增加被跟踪实体的数量,并且对X1 MON 1X的调用可能最终需要更多时间。
再说一次,这只是一个猜测--但这是我开始寻找的地方。
w9apscun3#
这里并不是很中肯,但是您是否考虑过使用某种应用程序级缓存来查找客户id、部门id和类别?从您的帖子中并不清楚系统中存在多少这样的实体,或者查询获取这些实体涉及到什么。
但是,举个例子,如果系统中有一百万个类别,并且需要按类别名称查找它们的ID,那么在内存中始终保存一个名称/ID字典以供查找,这将保存您处理事务时到数据库的时间。(这里假设了一些事情,比如没有定期添加新的caregories)作为一般规则,到数据库的往返相对于内存中的操作是昂贵的。
khbbv19g4#
你必须端到端地分析每件事,看看你的时间到底花在哪里了。
如果行很宽,聚集索引不一定是最快的,最快的可能是覆盖非聚集索引,但这不是重点。
我希望获得更高的性能,如果你没有真正使用这些功能,你可能不得不放弃一些框架。如果你正在使用这些功能--嗯,这就是你所付出的代价......