0

問題

アプリ エンジンのカラオケ カタログ アプリを作成しています。このアプリは非常にシンプルです。最初のリリースでは、CSV の曲リストをカタログにインポートして表示する機能が提供されています。

CSV インポートに問題があります。開発環境で 17,500 レコードをインポートするには、非常に長い時間 (14 時間) かかります。実稼働環境では、約 1000 レコードをインポートし、コード 500 でクラッシュしました。ログを調べていますが、有用な手がかりは見つかりませんでした。

コード

class Song(ndb.Model):
    sid     = ndb.IntegerProperty()
    title   = ndb.StringProperty()
    singer  = ndb.StringProperty()
    preview = ndb.StringProperty()

    @classmethod
    def new_from_csv_row(cls, row, parent_key):
        song = Song(
                sid=int(row['sid']),
                title=row['title'],
                singer=row['singer'],
                preview=row['preview'],
                key=ndb.Key(Song, row['sid'], parent=parent_key))
        return song

class CsvUpload(webapp2.RequestHandler):
    def get(self):
        # code omit for brevity 

    def post(self):
        catalog = get_catalog(…) # retrieve old catalog or create new

        # upfile is the contents of the uploaded file, not the filename
        # because the form uses enctype="multipart/form-data"
        upfile = self.request.get('upfile')

        # Create the songs
        csv_reader = csv.DictReader(StringIO(upfile))
        for row in csv_reader:
            song = Song.new_from_csv_row(row, catalog.key)
            song.put()

        self.redirect('/upload')

サンプルデータ

sid,title,singer,preview
19459,Zoom,Commodores,
19460,Zoot Suit Riot,Cherry Poppin Daddy,
19247,You Are Not Alone,Michael Jackson,Another day has gone. I'm still all alone

ノート

  • 開発環境で、最大 17,500 件のレコードをインポートしようとしましたが、クラッシュは発生しませんでした
  • 最初は、レコードの作成と挿入は迅速に行われますが、データベースが数千に成長するにつれて、レコードの作成と挿入にかかる時間は 1 レコードあたり数秒に増加します。

インポート操作を高速化するにはどうすればよいですか? 提案、ヒント、またはヒントは大歓迎です。

アップデート

私は Murph のアドバイスに従いKeyProperty、曲をカタログにリンクするために使用しました。結果は、17,500 レコードで約 4 分 20 秒で、大幅な改善です。つまり、私は App Engine で NDB がどのように機能するかを完全には理解しておらず、まだまだ学ぶべきことがたくさんあります。

大きな改善ではありますが、4 分以上は確かに長すぎます。私は現在、Tim と Dave のアドバイスを調べて、アプリの応答時間をさらに短縮しています。

4

3 に答える 3

1

まず、ティムは正しい軌道に乗っています。60 秒以内に仕事を終わらせられない場合は、タスクを延期します。ただし、10 分以内に作業を完了できない場合は、 App Engine MapReduceに頼ってください。これにより、csv の処理作業が複数のタスクに分配されます。デモ プログラムを参照してください。必要な部分がいくつか含まれています。

開発時間の遅さについては--use_sqlite、dev_appserver の起動時にオプションを使用していますか?

マーフはあなたの問題の別の部分に触れています。エンティティ グループを使用すると、(エンティティ グループごとに) 挿入できる回数が制限されます。1 つの親を使用して 17,500 行を挿入しようとしても、うまくいきません。約5時間かかります。

では、一貫した読み取りが本当に必要なのでしょうか? これが 1 回限りのアップロードである場合、祖先以外の挿入を (プロパティとしてカタログを使用して) 実行してから、データが最終的に一貫性を持つようになるまで少し待つことはできますか? これにより、クエリが簡素化されます。

本当に一貫した読み取りが必要な場合は、書き込みを複数の親キーに分割する必要があります。これにより、祖先クエリがより複雑になるという犠牲を払って、書き込み速度が向上します。

于 2013-10-22T04:28:36.153 に答える
1

Google App Engine のデータストアでは、エンティティ グループへの書き込みは 1 秒あたり 1 回に制限されています。

すべての曲に「親」キーを指定しているため、それらはすべて 1 つのエンティティ グループになり、非常に遅くなります。

その関係を追跡するために KeyProperty を使用するだけでよいでしょうか? データの一貫性の問題が増える可能性がありますが、その方がはるかに高速です。

于 2013-10-21T20:43:24.020 に答える