[pgsql-jp: 28411] Re: updateの性能を向上

Iwao Watanabe iwao3 @ DSL.gr.jp
2002年 12月 21日 (土) 15:55:50 JST


こんにちは。

----- Original Message ----- 
From: <fukudami @ ntes.nec.co.jp>
To: <pgsql-jp @ ml.postgresql.jp>
Sent: Friday, December 20, 2002 8:34 PM
Subject: [pgsql-jp: 28403] updateの性能を向上


> 現状、普通にupdateを使用してDBを更新しているのですが、どうも
> 望んだ性能が出ません。現在約40万件レコード登録してあるテーブル
> に対し、下記の様な方式でupdateを実行すると、約15分程度かかって
> しまいます。更新対象のレコード数はそれほど多くは無い(と言っても
> ばらつきはありますが)ので、可能ならば2〜3分程度の性能にしたいです。
> 更新対象のレコード数は、一度に500〜3000程度です。

RDBMSにとって、更新は重たい処理です。
同時利用者がいるかもしれないことが前提なので、
ある人物が更新しているあいだでも、
別の人がその前の状態を見えるようになっているのです。
この約束を守るために更新処理は実質、
SELECT(対象を見つける) +
INSERT(更新後のデータを登録する:
ただしトランザクションが終了するまで他人に見えない) + 
DELETE(もとのデータを消す: 本当に消すのはトランザクションの終了時なので
UPDATEの時には 見つけやすいように印をつけているだけかも) をしているのです。

UPDATE の応答速度が妥当かどうか気になるなら、
40万件の実データに対して 
SELECTとINSERTとDELETEを個別にかけてみればよいです。
おそらく UPDATEコマンドでかかる時間と、そう差は無いはずです。
同様に遅いのなら、今あるハードウェアで そのDBMSを選ぶ限り
そういうものなのです。
もし差があるなら、クエリの書き方次第で
早くなる余地があるかもしれません。

速度を追求するなら(それが要件として必要なこともあります)
RDBMSで使うテーブルを設計するときに
UPDATE処理が なるべく生じないようにするべきです。

RDBMSはSELECTが一番速く動作します。INDEXはそのための仕掛けですね。
次にINSERTが早く動作します。CONSTRAINTを調べるだけですみますから。
次はDELETEです。消す前に対象を探す必要があるのでSELECTしたあとにDELETEしています。
繰り返しになりますが、UPDATE は大変です。SELECT+INSERT+DELETE していますから。

そして、これを踏まえた対応は… 速度が要求される場面では、
とりあえずDBには更新後の値をINSERTだけしておきます。
人が欲しいデータがあれば、SELECTの条件を工夫して
古いデータを抽出しないようにします。一度に数千件のデータを
見れる人はいませんから 一度に取り出すデータを小出しにしても
オペレータはあまりイライラしません。
あとでゆっくり時間が取れるときに 古いデータ削除するするのです。
こうすると見かけ上 早く動作するシステムができます。
(いえ、オペレータにとっては間違いなく早く動作するシステムです。)

人が見ないようなデータなら少々遅くても、
コンピュータがせっせと動いてくれるので
文句をいう人は、まずいません。
40万件のデータ処理に15分が遅いですか?
充分早いではないですか。
人が同じことを処理して15分で終わるのでしょうか。

(最後はちょっと詭弁)





pgsql-jp メーリングリストの案内