2012-04-30 20 views
0

データストアが参照されたエンティティに対して追加のクエリを実行するため、アプリケーションに待ち時間の問題があります。私はgood adviceを受け取っています。これは、get_value_for_datastore()関数を使用して単一値のプロパティに対してこれを処理する方法です。しかし、私のアプリケーションも以下のコードに示すように1対多の関係を持っています。これらのエンティティをプリフェッチする方法が見つかりませんでした。結果として、200個のドキュメントとそれに関連するドキュメントファイル(> 6000ミリ秒)のテーブルを表示しようとすると、許容できない遅延が発生します。データストア内で1対多のクエリを最適化する方法

これを解決する方法はあります(おそらく以上10.000ドキュメントまたはDocumentFilesがあってはなりませんか)?

models.py

class Document(db.Expando): 
    title = db.StringProperty() 
    lastEditedBy = db.ReferenceProperty(DocUser, collection_name = 'documentLastEditedBy') 
... 

class DocUser(db.Model): 
    user = db.UserProperty() 
    name = db.StringProperty() 
    hasWriteAccess= db.BooleanProperty(default = False) 
    isAdmin = db.BooleanProperty(default = False) 
    accessGroups = db.ListProperty(db.Key) 
... 

class DocumentFile(db.Model): 
    description= db.StringProperty() 
    blob = blobstore.BlobReferenceProperty() 
    created = db.DateTimeProperty() # needs to be stored here in relation to upload/download of everything  
    document = db.ReferenceProperty(Document, collection_name = 'files') 

    @property 
    def link(self):  
     return '<a href="/file/serve/%s">%s</a>' % (self.key().id(),self.blob.filename) 
... 

main.py

docUsers = DocUser.all() 
docUsersNameDict = dict([(i.key(), i.name) for i in docUsers]) 

documents = Document.all() 
for d idocuments:   
    out += '<td>%s</td>' % d.title  
    docUserKey = Document.lastEditedBy.get_value_for_datastore(d) 
    out +='<td>%s</td>' % docUsersNameDict.get(docUserKey) 
    out += '<td>'       
    # Creates a new query for each document, resulting in unacceptable latency 
    for file in d.files: 
     out += file.link + '<br>' 
    out += '</td>' 

答えて

2

非正規化してリンクを得ることは速くなるように、ドキュメント内のリンクを格納します。

DocumentFileを更新するときに、関連するドキュメントを更新する必要があることに注意する必要があります。これは、データストアからリンクを更新するよりもはるかに頻繁に読むことを前提として動作します。

非正規化は、多くの場合、App Engineのパフォーマンスが低いために修正されます。

+0

ありがとうございます。これを逆正規化する。それはドキュメントで約束されたクリーンなデザインを使用することができないが、それは人生が時々ある方法です。 –

1

ファイルを非同期で読み込みます。 d.filesでget_value_for_datastoreを使用します。これはキーのコレクションを戻す必要があります。db.get_async(key)を使用して将来のオブジェクトを戻すことができます。手続き的に結果を手続き的に書くことはできませんが、すべてのドキュメントの部分的なリクエスト/ディクショナリをアセンブルし、将来のgets()のコレクションを組み立ててから、反復を行う結果をビルドすると、{〜0msの待ち時間}をブロックすることなく終了する先物を確定することができます。

基本的に、2回の反復が必要です。最初の反復は、必要なファイルを非同期的に要求し、2回目の反復は完了し、獲得を確定し、応答を構築します。

https://developers.google.com/appengine/docs/python/datastore/async

+0

ありがとうございますが、get_value_for_datastoreはQueryオブジェクト(Document.files.get_value_for_datastore(d))を返すだけで、うまくいきません。 –

+0

完全な照会がその照会を反復するには高価すぎる場合は、射影照会を使用して 'リンク'プロパティーのみを戻すことをお勧めしますか? https://developers.google.com/appengine/docs/python/datastore/queries#Query_Projection query.fetch(projection =( 'links'))またはquery.run(projection =( 'links'))リンクがインデックスフィールドである場合は、はるかに高速なクエリを返します。私はまだあなたがクエリを実行せずにあなたが望むファイルのキーにアクセスできるはずだと思います。それらはあなたの文書のどこかに返されなければなりません... – Ajax

関連する問題