【发布时间】:2012-09-25 07:20:07
【问题描述】:
这个问题是问以下两种方法中哪一种更受鼓励(以及出于什么原因)?
我正在使用 C# 4.0 在 ServiceStack REST 应用程序中使用 FluentNHibernate,但这个问题对于 NHibernate LINQ 查询很常见。
是否更鼓励:
(方法 1) 快速运行 简单 查询,该查询返回与用户 ID 匹配的所有行:
// Query the User by id
var user = session.Get<User>(request.UserId);
然后在返回的 List 上单独使用 LINQ 进一步缩小结果:
// 'User' contains a 'List<Location>'
var locations = user.Locations.Where(location =>
location.Timestamp >= (request.MinTimestamp.HasValue ? request.MinTimestamp.Value : 0) &&
location.Timestamp <= (request.MaxTimestamp.HasValue ? request.MaxTimestamp.Value : DateTime.Now.ToTimestamp()));
return locations;
(方法 2)或,是否更鼓励在单个查询中运行 更复杂的 查询:
var locationsQuery = session.QueryOver<LocationModel>()
.Where(table => table.User.Id == request.UserId)
.And(table => table.Timestamp >= (request.MinTimestamp.HasValue ? request.MinTimestamp.Value : 0))
.And(table => table.Timestamp <= (request.MaxTimestamp.HasValue ? request.MaxTimestamp.Value : DateTime.Now.ToTimestamp()));
return locationsQuery.List();
如果我的目标是:
a) 更快的执行时间
基准(修订)
修改后的完整测试代码:http://pastebin.com/0ykKwcxX
基准输出:
方法 1 耗时 147.291 秒超过 5000 次迭代。
上一次迭代的查询结果:
{ 时间戳=1348659703485,纬度=179.40000,经度=209.40000 }
{ 时间戳=1348659703486,纬度=179.55000,经度=209.55000 }
{ 时间戳=1348659703487,纬度=179.70000,经度=209.70000 }
{ 时间戳=1348659703488,纬度=179.85000,经度=209.85000 }
{ 时间戳=1348659703489,纬度=180.00000,经度=210.00000 }
方法 2 耗时 133.728 秒超过 5000 次迭代。
上一次迭代的查询结果:
{ 时间戳=1348659703485,纬度=179.40000,经度=209.40000 }
{ 时间戳=1348659703486,纬度=179.55000,经度=209.55000 }
{ 时间戳=1348659703487,纬度=179.70000,经度=209.70000 }
{ 时间戳=1348659703488,纬度=179.85000,经度=209.85000 }
{ 时间戳=1348659703489,纬度=180.00000,经度=210.00000 }
区别:方法 2 快了大约 13.5 秒。
b) 长期重复使用和稳定性
【问题讨论】:
-
在执行时间方面,你为什么不测试一下看看?
-
我很惊讶第二种方法似乎更慢。你检查过 NHibernate 执行的 SQL 查询吗?可以发一下吗?
-
在第一种情况下,您应该得到两个查询,例如:select * from Users where UserId =
, select * from Locations where UserId = 。在第二种情况下,我们应该只有一个查询:select * from Locations where UserId = 。在您的测量中,第二个选项几乎慢了 2 倍 - 这让我感到惊讶。 -
如果将
DateTime.Now.Timestamp移出查询并将其存储在临时变量中会怎样?这是否在数据库中重复映射和执行?正如@lowleveldesign 所说,看到 NHibernate 生成的原始 SQL 会很有趣。 -
var locationsQuery = ...实际上根本没有查询数据库。var是IQueryOver<LocationModel>而不是List<LocationModel>。测试是否相等?
标签: performance linq fluent-nhibernate benchmarking queryover