1

私はDjangoを初めて使用し、データベースに〜60,000の「プロジェクト」モデルを持つアプリケーションを持っています。

この量は常に増え続けています。「プロジェクト」は私たちが作成した Django モデルです。私たちのアプリケーションは、定期的にこれらのプロジェクトを特定の順序でサイトに表示する必要があります。プロジェクトには 3 つのタイプがあり、type1、type2、type3 と呼びます。これらのプロジェクトも特定の時間に期限切れになり、その量は常に増加しているため、静的なリストを作成して使用することはできず、動的でなければなりません。次のようなプロジェクトを表示する必要があります (1 ページあたり 32):

type1 type2 type3 type1
type2 type3 type1 type2 
type3 type1 type2 type3
type1 type2 type3 type1
type2 type3 type1 type2
type3 type1 type2 type3
type1 type2 type3 type1
type2 type3 type1 type2 

また、これらのプロジェクトを表示するための無限スクロールも実装しているため、リストは同じ順序で表示し続ける必要があります。例: 上記のページ 2 は type3 で始まります。

  1. 現在、タイプごとに 3 つのクエリを作成しています。
  2. それぞれのリストを作成します。
  3. 別のリストを作成します。
  4. 次に、プロジェクトを繰り返し、3 のリストに交互に追加します。
  5. Paginator を作成し、特定のページを返します。

これらのリストをすべて作成して繰り返し処理するのは非常にコストがかかることを理解していますが、スピードアップする方法に苦労しています。私が試した方法の 1 つはMemcachedです。

1500 のプロジェクトを Memcached に保存していますが、応答は非常に高速です。しかし、キーの有効期限が切れると、アプリケーションはそのすべてを再度実行する必要があります。私が考えたことの 1 つは、管理コマンド ( https://docs.djangoproject.com/en/dev/howto/custom-management-commands/ ) を作成し、crontrab から実行して、このリストが常にメモリ内にあることを確認することです。crontab (データ プル) で既にいくつかのコマンドを実行しているので、これはひどいことではありません。

また、フィルターを使用して QuerySet を作成でき、実際に必要になるまでデータベースにアクセスしないという事実を利用しようとしました。しかし、ページごとに 32 個のプロジェクトを表示しているため、実際にこれを実装する際に問題が発生しています。これは、あるタイプの 10 個、別のタイプの 11 個、別のタイプの 11 個を表示するためです。

異なる種類の量は同じではありません。約あります:

type1: ~500
type2: ~36,000
type3: ~24,000

このため、type1 が終了したときと type2 が終了したときに何をすべきかについて問題が発生しました (誰かがここまで到達する可能性はほとんどありませんが、それでも説明する必要があります)。

編集:回答ありがとうございます!これは私の学校の絶頂プロジェクトです。Python を使用するのはこれが初めてです。インターンシップで Groovy と Grails を使用したことがあるので、ORM の概念に精通しています。少しコードを提供します:

def index(request):
    type1Projects = list(project.objects.filter(type=type1))
    type2Projects = list(project.objects.filter(type=type2))
    type3Projects = list(project.objects.filter(type=type3))

    projects = list()

    while(len(type1Projects) > 0 or len(type2Projects) > 0 or len(type3Projects) > 0) :
        if(len(type1Projects) > 0) :
            projects.append(type1Projects.pop(0))
        if(len(type2Projects) > 0) :
            projects.append(type2Projects.pop(0))
        if(len(type3Projects) > 0) :
            projects.append(type3Projects.pop(0))

    paginator = Paginator(projects, 32)

    page = request.GET.get('page', 1)
    render_to_response('fake.html', {'projects':paginator.page(page)}, RequestContext(request))

ご覧のとおり、これらのクエリを評価してリストをメモリにロードすると、多くのオーバーヘッドが発生します。その後、プロジェクト リストの繰り返しと作成にも時間がかかります。

私たちの絶頂クライアントが交互の型を必要とする前は、次のように返していました:

def index(request) :
    projects = projects.objects.all()

    paginator = Paginator(projects, 32)

    page = request.GET.get('page', 1)
    render_to_response('fake.html', {'projects':paginator.page(page)}, RequestContext(request))

これらは、概念を説明するためだけにこの関数を簡略化したものです。2 つ目は、必要なものだけを評価するため高速でした。すべてがメモリにロードされてから反復されるため、交互の方法は完全に時間がかかりすぎます。

これは、Django QuerySet の遅延評価を利用するために私が試みたバージョンです。

def index(request) :
    type1Projects = project.objects.filter(type=type1)
    type2Projects = project.objects.filter(type=type2)
    type3Projects = project.objects.filter(type=type3)

    page = request.GET.get('page', 1)

    type1Pag = Paginator(type1Projects, 11)
    type2Pag = Paginator(type2Projects, 11)
    type3Pag = Paginator(type3Projects, 11)

    type1List = list(type1Pag.page(page))
    type2List = list(type2Pag.page(page))
    type3List = list(type3Pag.page(page))

    projects = list()

    while(len(type1List) > 0 or len(type2List) > 0 or len(type3List) > 0) :
        if(len(type1List) > 0) :
            projects.append(type1List.pop(0))
        if(len(type1List) > 0) :
            projects.append(type2List.pop(0))
        if(len(type3List) > 0) :
            projects.append(type3List.pop(0))


    render_to_response('fake.html', {'projects':projects}, RequestContext(request))

このバージョンはかなり高速に動作し、実際に実装されたバージョンよりも単純なバージョンです。これは、開始するプロジェクト タイプを指定し、ページあたり 32 プロジェクトに制限するロジックがあったためです。しかし、ページごとに 1 種類のプロジェクトがありません。より遠くのページに到達したら、このタイプのリストのプロジェクト #5 から開始して次のページに移動するロジックを実装するのに苦労しました。

これが少し明確になることを願っています。昨夜は混乱を招いて申し訳ありませんでした...私は決勝の準備をしていて、疲れていた/おそらく昨夜はまっすぐ考えていませんでした. raw SQL と NoSql について調べます。

@Saransh Mohapatra RedisまたはMemcacheを直接使用するとはどういう意味ですか? 現在、Memcache を使用して、リストから最初の 1500 個のプロジェクトを保存しています。問題は、キーを 5 ~ 10 分間だけ有効にしたいことです。そのため、キーの有効期限が切れて誰かがサイトにアクセスすると、応答が遅くなります。そのため、管理コマンドを作成し、crontab を使用して 4 分ごとに実行し、キーを 10 分間有効にすることについて話していました。これを行った場合、リストは常にそこにありますが、これが最善の方法であるかどうかはわかりません.

4

1 に答える 1

0

コードを見ずに何かを提案するのは難しいです。しかし、私が推測できる限り、モデルには関係がないため、従来の sql を使用するよりも NoSql を使用すると、はるかに高速になります。

これにより、はるかに高速になり、毎回キャッシュする必要がなくなります。キャッシュのみに使用するのではなく、Reddis を調べたり、memcache を直接使用したりすることもできます。これらは基本的に一種のキー値ストアであるため、キャッシュ プロジェクトではキーを、その詳細を値にすることができます。見てみる

于 2012-12-01T08:24:21.147 に答える