在fair amount of research和一些errors之后,我修改了我的代码,以便每次查询数据库时都会创建一个新的DataContext或插入数据。并且经常查询数据库 - 对于每个处理的250k事务,在插入事务之前,将查询数据库以获取客户ID,部门ID和类别。
所以现在我正在尝试优化代码,因为它每秒只处理大约15个事务。我删除了一些无关的查询并添加了一些索引,并将其提高到30 /秒。然后我想,尽管每个人都说DataContext是轻量级的,但是每个事务需要花费4倍的时间来创建一个新的,所以我尝试重用DataContext。令我惊讶的是,我发现重复使用上下文会导致性能降低到每秒10个事务!
为什么会出现这种情况?是因为DataContext将实体缓存在内存中,并在查询数据库之前首先搜索其内存列表?因此,例如,如果我正在寻找名为“MCS”的客户的客户ID(主键),并且客户名称列上有聚簇索引,以便数据库查询速度快,则在内存中查找会慢一点吗?
创建/部署如此多的数据库连接是否会减慢速度,或者这只是另一种过早的优化?如果确实如此,是否有办法重用DataContext但是它为每个linq-to-sql查询执行实际的数据库查询?
答案 0 :(得分:15)
这就是为什么重复使用DataContext不是最佳做法,来自MSDN DataContext documentation:
DataContext是所有人的来源 映射到数据库的实体 连接。 跟踪您的变化 对所有检索到的实体和 维护一个“身份缓存” 保证检索实体 不止一次代表 使用相同的对象实例。
通常,DataContext实例是 旨在持续一个“单位 工作“但你的应用程序定义 那个词。 DataContext是 轻便且不贵 创建。典型的LINQ to SQL 应用程序创建DataContext 方法范围或实例 昙花一现的成员 代表一组相关的逻辑 数据库操作。
如果您为大量查询重复使用DataContext,您的性能会因几种可能原因而降低:
如果DataContext的内存中的身份缓存变得如此之大以至于必须开始写入页面文件,那么你的性能将受到HD的读取头速度的限制,并且实际上没有理由使用缓存。
内存中的身份对象越多,每次保存操作所需的时间就越长。
基本上你正在做的是违反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字典以便随时查找将节省您前往您处理的事务的数据库。这可以大大提高性能(这假设了一些事情,比如没有定期添加新的护理)。作为一般规则,与内存操作相比,往返数据库的往返费用很高。