0

私は 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 によって生成された同じ SQL を ADO.Net で実行することでした。クエリは非常に高速に実行されました (ストップウォッチの経過時間は 0 です)。

plsql developer を使用してデータベースで同じクエリを実行すると、同じ高速な結果が得られました。これは、クエリでもデータベースでもないと思うことを示唆しています。

これをさらにデバッグするにはどうすればよいですか? nHibernate プロファイラーはこれに役立ちますか (現時点では利用できません)?

アイデアはありますか?

4

3 に答える 3

1

まず、プログラムの実行中にさらにいくつかの時点をキャプチャしてみてください。それが NHibernate コンポーネントであると仮定しましたが、特に最初のテストで 0 が返された場合、証明するのが難しくなるデータ ポイントがこれ以上ありません。

第 2 に、NHibernate シナリオの大きなコストは への呼び出しBuildSessionFactory()です。NHibernate は安価なセッション構築を行うように最適化されているため、このファクトリを一度作成すると、プログラムの存続期間全体で再利用することが期待されます。このイベントの周りにトレースポイントを配置すると、あなたの「費用」が見つかるかもしれません。

于 2012-06-27T06:46:05.083 に答える
0

問題は、主キー列のデータ型を指定しなかったということでした。これは、varchar(非Unicode)であることが判明しました。fluentは文字列がUnicodeにマップされると想定しているため、非Unicode列のデータ型を指定する必要があることがわかりました。

流暢な表記でカスタムタイプを設定する方法は次のとおりです。

 Map(x=>x.PersonId).CustomType("AnsiString");
于 2012-09-04T04:16:47.673 に答える
0

ここで大げさな推測をしなければならなかった場合、問題は nhibernate がデータベースを照会することではなく、sessionFactory および/またはセッションを構築するために支払っている初期コストであり、それが異常な遅延が発生している理由だと思います。

Jetbrains の dotTraceを使用して、実際のパフォーマンス ヒットがどこにあるのか (クエリの実行中など) を確認しないでください。サンプリング クエリを実行するだけで、各関数の正確な呼び出し回数でタイミングを取得できます。

PS: 私は Jetbrains とは何の関係もありません。満足している顧客が製品を勧めているだけです。

于 2012-06-27T06:11:27.970 に答える