1

包含 10000 行的数据库表 (PostgreSQL):

CREATE TABLE test
(
  id bigserial NOT NULL,
  text text,
  CONSTRAINT test_pkey PRIMARY KEY (id)
)

课程:

public class Test
{
    public virtual int ID { get; set; }
    public virtual string Text { get; set; }
}

public class TestMap : ClassMap<Test>
{
    public TestMap()
    {
        Table("test");
        Id(x => x.ID, "id");
        Map(x => x.Text, "text");
    }
}

这是我查询数据库的方式:

using (ISession session = SessionBuilder.OpenSession())
{
    Stopwatch s = new Stopwatch();

    s.Start();
    var result = session.QueryOver<Test>().Where(test => test.Text == "aaa").List();
    s.Stop();
    Console.WriteLine(s.ElapsedMilliseconds); // >150ms

    s.Restart();
    var result2 = session.QueryOver<Test>().Where(test => test.Text == "bbb").List();
    s.Stop();
    Console.WriteLine(s.ElapsedMilliseconds); // ~4ms
}

为什么第一个查询需要这么长时间?有没有办法加快速度?

4

3 回答 3

1

与数据库建立连接通常会产生开销,在这种情况下,由于连接池,您不会看到其他查询。根据您在那里的时间安排,我会说这就是您所看到的问题。

此外,请确保您只创建一次会话工厂并对其进行缓存,然后从中打开会话。我认为您不会根据您的时间遇到​​这种情况,但是如果配置足够小,它也可能是这样。

于 2013-05-14T02:55:32.850 回答
1

很可能是缓存。您没有可以帮助查询的索引,因此全表扫描是获得任一答案的唯一方法。第一个将由 DB 填充缓冲区和缓存(可能不会用于表扫描),但肯定 O/S 将缓存所有或部分磁盘页面。第二个查询将受益于那些在某个级别缓存的页面。

Craig 的建议也是关于缓存和启动的一个微妙的转折——你第一次做任何事情时往往会受到一点打击,你需要找出是什么。在 Web 应用程序中,您可以在应用程序接受请求之前进行一些启动。如果这更像是您无法掩饰热身的批处理,那么您可能只需要忍受它或放弃 nHibernate。

接受他的建议并衡量 Hibernate 中正在发生的事情。

于 2013-05-14T02:29:50.913 回答
0

可能的解决方案 1:
几年前我一直在研究性能问题,我发现的问题是 NHibernate 使用的 XML 序列化程序的初始化。我在 Jira 上报告了一个错误和修复: https ://nhibernate.jira.com/browse/NH-2958

尝试我对您的休眠源的修复,看看问题是否已解决。根据 jira 系统,该问题将在 nhibernate 的下一个版本中修复。

可能的解决方案 2:
如果解决方案 1 不起作用,请尝试在每个类映射的映射中将动态更新和动态插入设置为 true。NHibernate 在编译映射时会创建所有可能的查询。

于 2013-06-13T11:00:51.060 回答