在Oracle上流畅的nHibernate查询非常慢

时间:2012-06-27 05:42:49

标签: performance nhibernate fluent-nhibernate

我是nHibernate的新手,并且从简单的选择查询中获得了一些非常缓慢的结果。也许我错过了一些明显的东西。情况如下:

  • 我正在使用流利的nHibernate。
  • 我正在查询oracle数据库(10g),我正在尝试返回一个人对象。
  • 每张唱片约需16秒!

这是我流利的nHibernate代码:

public class Person
{
    public virtual string PersonId { get; set; }
    public virtual string FirstName { get; set; }
    public virtual string LastName { get; set; }
}

public class PersonMap : ClassMap<Person>
{
    public PersonMap()
    {
        Schema("MyTestDB");
        Table("Person");
        Id(i => i.PersonId);
        Map(i => i.FirstName);
        Map(i => i.LastName);
    }
}

以下是用于检索实际数据的代码:

var sessionFactory = Fluently.Configure().Database(OracleClientConfiguration.Oracle10.ConnectionString(@"User Id=tester;Password=tester99!;Data Source=MyTestDB;").ShowSql()).Mappings(m => m.FluentMappings.AddFromAssembly(Assembly.GetExecutingAssembly())).BuildSessionFactory();                   

    using (var session = sessionFactory.OpenSession())
    {           
        using (session.BeginTransaction())
        {
            Stopwatch stopWatch = new Stopwatch();
            stopWatch.Start();

            var person = session.QueryOver<Person>()
                                .Where(p => p.PersonId == "1").SingleOrDefault();

            stopWatch.Stop();

            var ts = stopWatch.Elapsed;
            var time = string.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds/10);

            Console.WriteLine("Retrieved object: Person, Id: {0}, First Name: {1}, Last Name: {2} in [{3}]", person.PersonId, person.FirstName, person.LastName, time);
        }
    }

PersonId列已建立索引并且是主键。

到目前为止,我试图解决这个问题的方法是运行nHibernate使用ADO.Net生成的相同sql。查询运行得非常快(秒表获得的经过时间为0)。

使用plsql developer在数据库上运行相同的查询给出了相同的快速结果。这表明我认为它不是查询,也不是数据库。

如何进一步调试? nHibernate profiler会帮助解决这个问题(我现在还没有这个)吗?

任何想法的人?

3 个答案:

答案 0 :(得分:1)

首先,您应该尝试在整个程序执行过程中捕获更多的时间点。您已经假设它是NHibernate组件,但没有更多的数据点很难证明,特别是当您的初始测试返回0时。

其次,NHibernate场景中的巨大成本是对BuildSessionFactory()的调用。 NHibernate经过优化,可以进行廉价的会话构建,因此它希望您创建一次这个工厂并在程序的整个生命周期中重复使用它。如果您在此事件周围添加跟踪点,您可能会发现“费用”。

答案 1 :(得分:0)

如果我不得不在这里猜测,问题不在于nhibernate查询数据库我认为这是你为构建sessionFactory和/或session而付出的初始成本,这就是你看到不寻常的延迟的原因

为什么不使用Jetbrains dotTrace并查看实际性能命中的位置,如果它在运行查询或其他内容时。只需运行一个抽样查询,您就可以获得每个函数的确切调用次数。

P.S:我和jetbrains没有关系,只是推荐该产品的客户很满意。

答案 2 :(得分:0)

问题最终是我没有指定主键列的数据类型,结果是varchar(非unicode)。事实证明,您需要为非unicode列指定数据类型,因为Fluent假设字符串映射到uni代码。

这是如何以流利的符号设置自定义类型:

 Map(x=>x.PersonId).CustomType("AnsiString");