質問

私はDjangoビューを持っています。これは、ループ内に500〜5000個の新しいデータベースINSERTSを作成します。問題は、本当に遅いことです! Postgres 8.3では1分あたり約100の挿入を取得しています。以前はより小さなハードウェア(より小さなEC2インスタンス)でMySQLを使用していましたが、この種の速度の問題は一度もありませんでした。

詳細: Ubuntu Server 9.04上のPostgres 8.3。 サーバーは「大」ですEBS(ext3)上のデータベースを備えたAmazon EC2-11GB / 20GB。

こちらは私のpostgresql.confの一部です-さらに必要な場合はお知らせください

shared_buffers = 4000MB
effective_cache_size = 7128MB

私のpython:

for k in kw:
        k = k.lower()
        p = ProfileKeyword(profile=self)
        logging.debug(k)
        p.keyword, created = Keyword.objects.get_or_create(keyword=k, defaults={'keyword':k,})
        if not created and ProfileKeyword.objects.filter(profile=self, keyword=p.keyword).count():
            #checking created is just a small optimization to save some database hits on new keywords
            pass #duplicate entry
        else:
            p.save()

上からの出力:

top - 16:56:22 up 21 days, 20:55,  4 users,  load average: 0.99, 1.01, 0.94
Tasks:  68 total,   1 running,  67 sleeping,   0 stopped,   0 zombie
Cpu(s):  5.8%us,  0.2%sy,  0.0%ni, 90.5%id,  0.7%wa,  0.0%hi,  0.0%si,  2.8%st
Mem:  15736360k total, 12527788k used,  3208572k free,   332188k buffers
Swap:        0k total,        0k used,        0k free, 11322048k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                                                                                            
14767 postgres  25   0 4164m 117m 114m S   22  0.8   2:52.00 postgres                                                                                                                                            
    1 root      20   0  4024  700  592 S    0  0.0   0:01.09 init                                                                                                                                                
    2 root      RT   0     0    0    0 S    0  0.0   0:11.76 migration/0                                                                                                                                         
    3 root      34  19     0    0    0 S    0  0.0   0:00.00 ksoftirqd/0                                                                                                                                         
    4 root      RT   0     0    0    0 S    0  0.0   0:00.00 watchdog/0                                                                                                                                          
    5 root      10  -5     0    0    0 S    0  0.0   0:00.08 events/0                                                                                                                                            
    6 root      11  -5     0    0    0 S    0  0.0   0:00.00 khelper                                                                                                                                             
    7 root      10  -5     0    0    0 S    0  0.0   0:00.00 kthread                                                                                                                                             
    9 root      10  -5     0    0    0 S    0  0.0   0:00.00 xenwatch                                                                                                                                            
   10 root      10  -5     0    0    0 S    0  0.0   0:00.00 xenbus                                                                                                                                              
   18 root      RT  -5     0    0    0 S    0  0.0   0:11.84 migration/1                                                                                                                                         
   19 root      34  19     0    0    0 S    0  0.0   0:00.01 ksoftirqd/1 

その他の詳細が役立つかどうか教えてください。

役に立ちましたか?

解決

まず、ORM操作は常に純粋なSQLよりも遅くなります。 ORMコードで大規模なデータベースの更新プログラムを作成し、それを実行するように設定したことがありますが、ほんの数分で完了した数時間後に終了しました。 SQLで書き直した後、全体が1分未満で実行されました。

第二に、ここでのコードは、データセットのすべての行に対して最大4つの個別のデータベース操作を実行していることに注意してください-get_or_createの get 、または create 、フィルターの count 、最後に save 。これは多くのデータベースアクセスです。

最大5000個のオブジェクトはそれほど大きくないことを念頭に置いて、開始時にデータセット全体をメモリに読み込むことができるはずです。次に、単一の filter を実行して、既存のすべてのKeywordオブジェクトを一度に取得し、キーワード get_or_create に膨大な数のクエリを保存し、重複をインスタンス化する必要もありません。そもそもProfileKeywords。

他のヒント

このようなバルク操作が遅い一般的な理由の1つは、各挿入が独自のトランザクションで発生することです。それらすべてを単一のトランザクションで発生させることができれば、はるかに高速になります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top