Nhibernate,痛苦的慢查询,我做错了吗?

时间:2011-07-26 11:45:14

标签: c# nhibernate

在询问特定的nhibernate问题时,我遇到了一些主要的性能问题。

我有两个表,A和B,其中A有~4000行,B有~50 000行。 A和B之间的关系是一对多的。

所以我要问的问题需要加载A中的所有entites,然后强制加载B中的所有实体,因为我想聚合B中的实体。

我正在使用fluenthibernate并将其配置为允许延迟加载,这适用于所有其他问题,除了这个我必须加载~50000个实体,这个数字可能会以每月50k的速度增长。这个问题花了一分多钟才能现在问(可能更慢)

我已经完成了明显的优化:只创建一个sessionfactory,懒惰加载没有关闭。

所以我的问题是,在这方面,nhibernate会慢吗? (也就是说,我应该使用常规SQL问题而不是nhibernate来构建我的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");
}

然后在我的回购中我使用此查询:

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);
            }

2 个答案:

答案 0 :(得分:3)

选择任意大小的50,000行并不会很快,但考虑使用子选择获取策略 - 它应该在你的场景中工作得更好。另外,请确保您的数据库中有外键索引。

There's an example of what could be happening at the NHProf site

编辑:如果您正在使用NHibernate进行任何工作,我会完全推荐NHProf - 这是获得WIN的快捷方式。

答案 1 :(得分:3)

我发表评论然后重新阅读你的问题并怀疑你可能正在以一种不理想的方式使用NHibernate。你说你正在拉桌子B行聚合它们。您是否使用LINQ或 之后的某些内容通过NH提取个人记录?

如果是这样,您可能需要考虑利用NH的功能来创建将为您执行聚合的投影。通过这种方式,NH将生成用于执行聚合的SQL,这在大多数情况下比执行4000次相关项检索然后在代码中执行聚合要快得多。

这个问题可能会让你开始:What's the best way to get aggregate results from NHibernate?

<强>更新
是的,看看你的代码你正在禁用延迟加载,它会为你的每个聊天项启动一个单独的查询,以便提取评论。这是永远的,因为你基本上做了8000次单独的查询。

您似乎正在尝试按小时返回评论计数。您可以通过按DATEPART SQL表达式分组来执行一些手动SQL来分割注释时间戳,或者将datepart eval合并到您的条件中,例如:{SO}问题:How to use DatePart in an NHibernate Criteria Query