7

10,000 レコード/秒の速度でレコードをデータベースに格納する必要があるという要件があります (いくつかのフィールドにインデックスを付けます)。1 つのレコードの列数は 25 です。1 つのトランザクション ブロックで 100,000 レコードのバッチ挿入を行っています。挿入率を向上させるために、テーブルスペースをディスクから RAM に変更しました。これにより、1 秒あたり 5,000 回の挿入しか達成できません。

また、postgres 構成で次の調整を行いました。

  • インデックス : いいえ
  • fsync : false
  • ロギング:無効

その他の情報:

  • テーブルスペース: RAM
  • 1 行の列数 : 25 (ほとんどが整数)
  • CPU : 4 コア、2.5 GHz
  • RAM:48GB

データベースがディスクに何も書き込んでいないときに (RAM ベースのテーブルスペースを使用しているため)、単一の挿入クエリに平均で約 0.2 ミリ秒かかるのはなぜでしょうか。私が間違っていることはありますか?

助けていただければ幸いです。

プラシャント

4

4 に答える 4

16

高速データ読み込み

  1. データを CSV に変換します。
  2. 一時テーブルを作成します(ご指摘のとおり、インデックスなし)。
  3. COPY コマンドを実行します。\COPY schema.temp_table FROM /tmp/data.csv WITH CSV
  4. 非一時テーブルにデータを挿入します。
  5. インデックスを作成します。
  6. 適切な統計を設定します。

その他の推奨事項

大量のデータの場合:

  1. データを子テーブルに分割します。
  2. SELECTほとんどのステートメントが使用する列の順に挿入します。つまり、物理モデルを論理モデルに合わせるようにしてください。
  3. 構成設定を調整します。
  4. インデックスを作成しCLUSTERます (左側の最も重要な列)。例えば:
    UNIQUE INDEX を作成する Measurement_001_stc_index
      オン 気候.測定_001
      btree の使用
      (station_id、撮影、category_id);
    ALTER TABLE Climate.measurement_001 CLUSTER ON 測定_001_stc_index;

構成設定

4GBのRAMを搭載したマシンで、次のことを行いました...

カーネル構成

プログラムが共有メモリのゴブを使用しても問題ないことをカーネルに伝えます。

sysctl -w kernel.shmmax=536870912
sysctl -p /etc/sysctl.conf

PostgreSQL の設定

  1. 編集/etc/postgresql/8.4/main/postgresql.confして設定:
    共有バッファ = 1GB
    temp_buffers = 32MB
    work_mem = 32MB
    Maintenance_work_mem = 64MB
    seq_page_cost = 1.0
    random_page_cost = 2.0
    cpu_index_tuple_cost = 0.001
    effective_cache_size = 512MB
    チェックポイント_セグメント = 10
  2. 必要に応じて値を微調整し、環境に合わせてください。後で適切な読み取り/書き込みの最適化を行うために、おそらくそれらを変更する必要があります。
  3. PostgreSQL を再起動します。

子テーブル

たとえば、さまざまなカテゴリに分類された、天気に基づくデータがあるとします。巨大なテーブルを 1 つ持つのではなく、複数のテーブル (カテゴリごとに 1 つ) に分割します。

マスターテーブル

CREATE TABLE climate.measurement
(
  id bigserial NOT NULL,
  taken date NOT NULL,
  station_id integer NOT NULL,
  amount numeric(8,2) NOT NULL,
  flag character varying(1) NOT NULL,
  category_id smallint NOT NULL,
  CONSTRAINT measurement_pkey PRIMARY KEY (id)
)
WITH (
  OIDS=FALSE
);

子テーブル

CREATE TABLE climate.measurement_001
(
-- Inherited from table climate.measurement_001:  id bigint NOT NULL DEFAULT nextval('climate.measurement_id_seq'::regclass),
-- Inherited from table climate.measurement_001:  taken date NOT NULL,
-- Inherited from table climate.measurement_001:  station_id integer NOT NULL,
-- Inherited from table climate.measurement_001:  amount numeric(8,2) NOT NULL,
-- Inherited from table climate.measurement_001:  flag character varying(1) NOT NULL,
-- Inherited from table climate.measurement_001:  category_id smallint NOT NULL,
  CONSTRAINT measurement_001_pkey PRIMARY KEY (id),
  CONSTRAINT measurement_001_category_id_ck CHECK (category_id = 1)
)
INHERITS (climate.measurement)
WITH (
  OIDS=FALSE
);

テーブル統計

重要な列のテーブル統計を増やします。

ALTER TABLE climate.measurement_001 ALTER COLUMN taken SET STATISTICS 1000;
ALTER TABLE climate.measurement_001 ALTER COLUMN station_id SET STATISTICS 1000;

VACUUMtoとafter を忘れないでくださいANALYSE

于 2010-05-28T20:12:14.240 に答える
5

あなたはあなたの挿入物をシリーズとしてやっていますか

INSERT INTO tablename (...) VALUES (...);
INSERT INTO tablename (...) VALUES (...);
...

または 1 つの複数行の挿入として:

INSERT INTO tablename (...) VALUES (...),(...),(...);

2番目のものは、10万行で大幅に高速になります。

ソース: http://kaiv.wordpress.com/2007/07/19/faster-insert-for-multiple-rows/

于 2010-05-28T06:41:07.803 に答える
3

xlog (WAL セグメント) も RAM ドライブに配置しましたか? そうでない場合は、まだディスクに書き込んでいます。また、wal_buffers、checkpoint_segments などの設定はどうですか? wal_buffers で 100,000 レコード (単一のトランザクション) をすべて取得する必要があります。このパラメーターを大きくすると、PostgreSQL が、オペレーティング システムのデフォルト構成で許可されているよりも多くの System V 共有メモリを要求する可能性があります。

于 2010-05-28T07:16:36.747 に答える
1

COPYの代わりに使用することをお勧めしますINSERT

また、postgresql.conf ファイルを微調整する必要があります。

http://wiki.postgresql.org/wiki/Performance_Optimizationについて読む

于 2010-05-28T19:55:57.863 に答える