2017-05-22 4 views
0

私のプログラムの一部は、データベースを照会して、特定の要素のすべての子要素、およびすべての子要素などを子要素がなくなるまで探し、リーフ要素を取得します。データベースは、2つの列を使用して必要な情報を格納します。要素のIDを持つ1つの列、子要素のIDを持つ別の列。平均的なユースケースでは、要素数が500を超えるツリーが生成され、すべてのクエリを完了するまでに30秒以上かかります。クエリを最適化し、サーバーのボトルネックを減らすためにできることはありますか?再帰関数でデータベースクエリを実行する最も速い方法は何ですか?

cursor = conn.cursor() 
rootNode = Node(initialId) 
nodeList.append(baseNode) # all nodes go into a list for debugging output 
buildTree(baseNode, cursor) 

def buildTree(self, node, cursor): 
    query = "SELECT childId FROM Pairs WHERE parentId=?" 
    cursor.execute(query, node.value) 
    results = cursor.fetchall() 
    for entry in results: # for each result returned, make a new node for each child 
          # and then query each child to see if it has children 
     if entry[0] is not None: 
      newNode = Node(entry[0], parent=node) 
      nodeList.append(newNode) 
      buildTree(newNode, cursor) 

ノードは、ノードのID、ノードが持つ可能性のある子孫、および親ノードを格納するためのデータ構造として機能する短いクラスです。私はpyodbcを使用してSQL Server '08に接続しています。

+0

おそらく関連:http://sqlmag.com/t-sql/transitive-closure –

+0

@Robᵩありがとう、それは助けになるようです。私はそれと一緒に遊んで、どのようにそれを参照してください。 – sommerjj

+0

再帰SQLを検討しましたか? SQL Server 2008 R2にはすでにそれがあるはずです。 – LukStorms

答えて

2

まず最初に、クエリロジックをモデル(ツリー表現)とは別にする必要があります。これにより、柔軟性を高めることができます。

1)recursive query in SQL serverを最初に使用して、すべての必要なデータを一度に取得することですが、SQLサーバーには再帰呼び出しの制限があるため注意が必要です。

2)2番目の方法は、最初のアプローチまたは次のアプローチを使用してストアドプロシージャを書き込む方法です。

3)次に、各項目ではなく各レベルを選択してデータベースクエリ数を最小限に抑えることです。このように: 1. [すべてのルート・ノード 2.すべてのIDを取得し、3を繰り返し2から....

4クエリ Inを使用して、すべての子ノードを照会)そして、あなたはのない本当に大きな数を持って最終的にあればレコードとそれらの数は、メモリ内のすべてのレコードをロードしてツリーを構築するだけでは、大幅に増加することはありません。これはコードの速度を落とすことができるが、レコードの数千分の1がないことを考えることはできません。

いずれのケースでも、データサイズやその他の要件に実際に依存します。例えば、オプション3は、ネストレベルが大きくない場合は正常に機能します。それ以外の場合は、コードと同じになります。

+0

再帰的なクエリを使用しました。すべてのレコードの一括選択を行った場合よりもはるかに高速で実行され、コードがより洗練されています。 – sommerjj

+0

その答えはあなたの状況に依存します。メモリ内のすべてのデータをロードすることは、他のものが不可能な場合は常に最後のオプションです。これが私のリストの最後のオプションです) –

関連する問題