2011-08-15 9 views
0

NHibernateを使用して、次のエンティティで構築されたグラフをリレーショナルデータベースにマップしようとしています(コードは不完全でデモ用です。潜在的にNodeクラスとEdgeクラスにはサブクラスがあり、すでにNodeクラスから継承した一連のサブクラスがあります。このモデルのすべての継承関係では、使用されるマッピングタイプはjoined-subclass(table-per-subclass)です。ノードとNHibernate - ネイティブSQLを使用したパフォーマンスチューニング

が多対一Edge.StartNodeからノード(.OutgoingEdges)に、次のように二重の多対1のマッピングが使用されているエッジ間の接続のため

class GraphObject { ... } 

class Node : GraphObject { 
    List<Edge> IngoingEdges; 
    List<Edge> OutgoingEdges; 
} 

class Edge : GraphObject { 
    Node StartNode { get; set; } 
    Node EndNode { get; set; } 
} 

。 Edge.EndNodeからノードへの多対1(.IngoingEdges)

プロジェクト(数百万のノードとエッジ)で膨大な量のデータを処理する必要があるため、 NHibernateはパフォーマンスの問題を提供し、最小限に抑えます。残念ながら、そのようなモデルを保存したり読み込んだりするのに約1時間かかることがあります。私が現在行っていることは、1つのステートメントで読み込みを終了し、どれくらい時間がかかるかを調べる方法を見つけることです。私はいくつかの試みを行い、Hibernate Profilerを使用して、データ永続性からグラフ全体をロードするようなことをするときにNHibernateフレームワークによって生成されたSQLステートメントを追跡しましたが、これまでのところ、どのような特定のエッジの開始ノードと終了ノードかを決定するための照会

select ... StartNode as ..、..Id as ..、...リンクリンクからリンクlink.StartNode = 10(ノードIDを示す数字)

これは、いわゆるN + 1の問題に苦しんでいることを意味します。 同様の問題を抱えている人がいるので、ネイティブSQLでこの特定のケースのパフォーマンスを他の方法で改善することができます。私は本当にそれを感謝します。不明点に関するご質問も歓迎します。

+0

どのバックエンドデータベースを使用していますか?それはSQL Serverですか? –

+0

答えはありませんが、私が愛している製品のプロモーションは、次のような問題に役立ちます:Nhibernate Profiler http://nhprof.com/ –

答えて

0

いくつかの最適化が頭に浮かぶ:StartNodeEndNode

この

// initialize the collections efficiently 
session.QueryOver<Node>() 
    .Where(n => n.Id == nodeId) 
    .Fetch(n => n.IngoingEdges) 
    .ToFuture(); 

firstNode = session.QueryOver<Node>() 
    .Where(n => n.Id == nodeId) 
    .Fetch(n => n.OutgoingEdges) 
    .ToFuture().Value; 

var egdeIds = firstNode 
    .SelectMany(n => n.IngoingEdges) 
    .SelectMany(edge => new [] { edge.StartNode.Id, edge.EndNode.Id }); 

EagerLoadNode(nodeIds); 

void EagerLoadNode(IEnumerable<int> nodeIds) 
{ 
    // initialize the collections efficiently 
    session.QueryOver<Node>() 
     .Where(n => n.Id.IsIn(nodeIds)) 
     .Fetch(n => n.IngoingEdges) 
     .ToFuture(); 

    firstNode = session.QueryOver<Node>() 
     .Where(n => n.Id.IsIn(nodeIds)) 
     .Fetch(n => n.OutgoingEdges) 
     .ToFuture(); 
} 
+0

ありがとう、firo。それは問題にいくつかの光を投げかけた。 –

関連する問題