【发布时间】:2016-11-23 21:08:57
【问题描述】:
我正在编写一个程序,其中我使用 NHibernate 使用两个数据库查询。第一个查询是一个大查询 - 带有两个连接的选择(大 SELECT 查询),其结果是大约 50000 条记录。查询大约需要 30 秒。程序的下一步是遍历这 50000 条记录,并对每条记录调用查询。这个查询是非常小的 COUNT 方法。
有两件有趣的事情很难:
如果我在大 SELECT 之前运行小 COUNT 查询,则 COUNT 查询大约需要 10 毫秒,但如果我在大 SELECT 查询之后运行它需要 8-9 秒。此外,如果我降低大 SELECT 查询的复杂性,我也会减少之后执行 COUNT 查询的时间。
如果我在 sql server management studio 上运行大 SELECT 查询需要 1 秒,但从 ASP.NET 应用程序需要 30 秒。
所以有两个主要问题。为什么在 ssms 中查询速度如此之快时,在代码中执行查询需要这么长时间?为什么大的 SELECT 查询会影响之后的小 COUNT 查询。
我知道这个问题有很多可能的答案,但我用谷歌搜索了很多,这就是我尝试过的:
- 设置 asp.net 应用和 ssms 的 SET 参数相同,避免查询计划不同
- 清除 ssms 缓存,因此良好的 ssms 结果不是由 ssms 缓存引起的 - 清除缓存后 1 秒的结果相同
大 SELECT 查询:
var subjects = Query
.FetchMany(x => x.Registrations)
.FetchMany(x => x.Aliases)
.Where(x => x.InvalidationDate == null)
.ToList();
小 COUNT 查询:
Query.Count(x => debtorIRNs.Contains(x.DebtorIRN.CodIRN) && x.CurrentAmount > 0 && !x.ArchivationDate.HasValue && x.InvalidationDate == null);
【问题讨论】:
-
正在生成的查询是什么?抓住它并在 SSMS 中运行它。 FetchMany 可能是这里的性能杀手。为什么要在查询中使用 FetchMany?看起来计数查询没有使用其中的任何信息。
-
这只是代码的一小部分,FetchMany 数据稍后将在应用程序中使用并且是必需的。 NHibernate 从上面的代码片段中产生的查询非常大,但我已经在 management studio profiler 中跟踪它并在 SSMS 中运行它,它花了 1 秒
-
那么可能是您的查询正在重新补充这么多对象。这需要很长时间。我会删除 FetchMany,直到您真正需要它们并添加一个投影,以便您只返回您需要的数据,而不是创建整个对象层次结构
-
如果我理解正确,我应该在没有 fetchmany 的情况下运行查询。比我可以在需要额外数据时运行 fetchmany 对吗?仍然,我不明白投影部分。什么是投影?我怎么能在这里使用它?
-
因此,在您的“大 SELECT 查询”中,您没有 .Select(x=> new someojbect {})。那就是投影。如果您没有投影,它将创建您的整个实体对象,以及根据映射文件中的规则创建的任何对象。
标签: asp.net sql-server nhibernate ssms