Nhibernate,非常慢的查询,我做错了吗?
本文关键字:错了 查询 非常 Nhibernate | 更新日期: 2023-09-27 18:03:25
在询问一个特定的nhibernate问题时,我遇到了一些主要的性能问题。
我有两个表,A和B,其中A有~4000行,B有~ 50000行。A和B之间的关系是一对多。
所以我问的问题需要加载A中的所有实体然后强制加载B中的所有实体因为我想聚合B中的实体
我正在使用fluenthibernate,并将其配置为允许惰性加载,这对于所有其他问题都非常有效,除了这个问题,我必须加载~50000个实体,这个数字可能会以每月50k的速度增长。现在问这个问题需要一分钟以上(可能更慢)
我已经做过的明显优化:只创建一个sessionfactory,不关闭lazyloading
所以我的问题是,nhibernate在这方面会变慢吗?(也就是说,我应该用常规的SQL问题而不是hibernate来构建我的DAL吗?)或者是否有一种方法可以提高性能。这是一个报表应用程序,所以不会有很多并发用户,但我仍然希望这个问题至少花5-10秒。
编辑添加代码:
public class ChatSessions
{
public virtual int Id { get; set; }
public virtual IList<ChatComments> Comments { get; set; }
public ChatSessions()
{
Comments = new List<ChatComments>();
}
}
public ChatCommentsMapping()
{
Id(x => x.Id);
References(x => x.ChatSession);
}
public class ChatComments
{
public virtual int Id { get; set; }
public virtual ChatSessions ChatSession{ get; set; }
public virtual string Comment { get; set; }
public virtual DateTime TimeStamp { get; set; }
public virtual int CommentType { get; set; }
public virtual bool Deleted { get; set; }
public virtual string ChatAlias { get; set; }
}
public ChatSessionsMapping()
{
Id(x => x.Id);
References(x => x.ChatRoom)
.Not.LazyLoad();
HasMany(x => x.Comments)
.Table("chatcomments");
}
在我的repo中,我使用这个查询:
public IList<ChatComments> GetChatCommentsBySession(int chatsessionid)
{
using(var session = _factory.OpenSession())
{
var chatsession = session.Get<ChatSessions>(chatsessionid);
NHibernateUtil.Initialize(chatsession.Comments);
return chatsession.Comments;
}
}
这个方法在每次Chatsession中调用一次。
我聚合的查询看起来像这样:
foreach (var hour in groupedByHour){
var datetime = hour.Sessions.First().StartTimeStamp;
var dp = new DataPoint<DateTime, double>
{
YValue = hour.Sessions.Select(x =>
_chatCommentsRepo.GetChatCommentsBySession(x.Id).Count)
.Aggregate((counter,item) => counter += item),
XValue = new DateTime(datetime.Year, datetime.Month, datetime.Day, datetime.Hour, 0, 0)
};
datacollection.Add(dp);
}
选择任意大小的50,000行永远不会很快,但是考虑使用子选择抓取策略—它在您的场景中应该工作得更好。此外,请确保在数据库中为外键设置了索引。
这是NHProf网站可能发生的事情的一个例子
EDIT:如果你正在使用NHibernate,我强烈推荐使用NHProf -这是一个快速进入WIN的方法。
我发表了一个评论,然后重新阅读了你的问题,并怀疑你可能以一种不理想的方式使用NHibernate。你说你要拉表B行来对它们进行聚合。您是否使用LINQ或在之后的集合上的其他东西来执行此操作,您已经通过NH提取了单个记录?
如果是这样,您可能需要考虑利用NH的功能来创建将为您执行聚合的预测。通过这种方式,NH将生成SQL来进行聚合,在大多数情况下,这将比在代码中执行相关项的4000次检索快得多。
这个问题可能会让你开始:从NHibernate获得聚合结果的最佳方式是什么?
是的,看看你的代码,你禁用了延迟加载,它会为每个聊天项目触发一个单独的查询,以便拉出评论。这需要花很长时间,因为你基本上要做8000个单独的查询。
看起来你想返回一个按小时计数的注释数。您可以通过DATEPART
SQL表达式分组来分割您的注释时间戳,或者将datepart eval合并到您的标准中,如以下问题:如何在NHibernate标准查询中使用datepart