2010-11-23 28 views
1

私はdjango-pistonを使用して内部クライアントにXMLフィードを送信するDjangoアプリを持っています。一般的に、これらはうまくいきますが、現在15分以上実行されているXMLフィードがあります。これによりタイムアウトが発生し、フィードが信頼できなくなります。Django ORM:大量のデータを適切に整理する

私はこの設定を改善できる方法を考えようとしています。データの再構成が必要な場合は、それも可能です。ここで

は、データ収集が現在どのように見えるかです:

class Data(models.Model) 
    # fields 

class MetadataItem(models.Model) 
    data = models.ForeignKey(Data) 

# handlers.py 
data = Data.objects.filter(**kwargs) 

for d in data: 
    for metaitem in d.metadataitem_set.all(): 
     # There is usually anywhere between 55 - 95 entries in this loop 
     label = metaitem.get_label() # does some formatting here 
     data_metadata[label] = metaitem.body 

もちろん、プログラムのコアは多くをやっているが、どこに問題がある、私はちょうど指摘しています。 dataという300のリストを持つと、信頼性がなくなりタイムアウトになります。

  • はすべてMetadataItem年代を取得するために、単一の大きなクエリをやって、その後、すべてのデータIDのコレクションを取得:私が試した何

    。最後に、私のループのそれらをフィルタリングします。これは、減少したクエリを保持するためです。

  • .values()を使用して、モデルインスタンスのオーバーヘッドを削減しました。私はこれまで1つの簡単な解決策を考えている

ひとつのアイデアはステップでキャッシュに書き込むことです。タイムアウトを減らすには最初の50個のデータセットを書き、キャッシュに保存したり、カウンタを調整したり、次の50個などを書き込んだりするなど、これを熟考する必要があります。

誰かが私に正しい方向にこれを導くのを助けることができます願っています。

+0

サブクエリを実行する必要がないようにデータを再構築する機会はありますか? – Evgeny

答えて

2

あなたが投稿したコードの問題は、Djangoには逆の関係で自動的に接続されているオブジェクトが含まれていないため、オブジェクトごとにクエリを作成する必要があることです。 Daniel Roseman points out in his blogのように、この周りに良い方法があります!

これはよくあなたの問題が解決しない場合は、あなたも

+0

これは私が探していたものです。 n + 1からの質問を減らしました... 3 :)ありがとう – Bartek

1

最初にすべてのデータIDを取得し、次にselect_relatedを使用してデータを取得し、それを単一の大きなクエリで取得することで、クエリの数をさらに減らすことができます。これは照会の数を大幅に削減しますが、照会のサイズは実用的ではないかもしれません。次のようなものがあります。

data_ids = Data.objects.filter(**kwargs).values_list('id', flat = True) 
for i in data_ids: 
    data = Data.objects.get(pk = i).select_related() 
    # data.metadataitem_set.all() can now be called without quering the database 
    for metaitem in data.metadataitem_set.all(): 
     # ... 

しかし、可能であれば、ウェブサーバー外のフィードを事前に計算することをお勧めします。おそらく、あなたがmemcacheに結果を保存できるのは、1 MBより小さい場合です。または、あなたはブロック上のクールな新しい子供の一人で、結果をRedisのような "NoSQL"データベースに格納することができます。または、ディスク上のファイルに書き込むこともできます。

+0

答えてくれてありがとう。残念なことに、スピードのあまり変化がないと全く同じ方法で 'select_related'を使ってみました。いくつかの改善がありましたが、それでもなお災害です。 – Bartek

+0

事前計算のアプローチはどうですか?あなたの制約を考えれば可能でしょうか? – knutin

+0

それは私が考えていたことの一つです。例えばセロリを設定して、変更されたフィードをキューに入れ(残念ながら毎日変わります)、処理します。私はおそらくこれをやっていますが、30分以上実行されているフィードがあり、それが1日に数回変更されている場合、私はキューのバックアップを恐れています。 – Bartek

0

データの構造を変更できる場合は、データストアを変更することもできますか?

CouchDBやMongoDBのようないくつかの構造を可能にする "NoSQL"データベースは、実際にはここでは役に立ちます。

すべてのデータアイテムに対して、ドキュメントがあるとします。文書には通常のフィールドがあります。また、メタデータのリストである「メタデータ」フィールドを追加します。

{ 
    'id': 'someid', 
    'field': 'value', 
    'metadata': [ 
     { 'key': 'value' }, 
     { 'key': 'value' } 
    ] 
} 

これで、データレコードに簡単にアクセスしてすべてのメタデータを取得できます。検索するには、 'data'ドキュメントのフィールドにインデックスを追加します。

私は、Mnesiaを使ったErlang/OTPのシステムで作業しました。これは、基本的にインデックスとヘルパーを持つキーバリューデータベースです。私たちは大成功に大きく寄与したネストされたレコードを使用しました。

私はこれを別の答えとして追加しました。これは別の答えとは全く異なります。

0

もう一つのアイデアは、セロリを使用することです... 1つの生のSQLクエリのすべてを取得しようとしているを見ている可能性があり(www.celeryproject.com) PythonとDjangoのタスク管理システムです。あなたは、主なアプリケーションサーバーを押さなくても、長時間実行されているタスクを非同期的に実行することができます。

関連する問題