現在、フィールドにワイヤレスモデムのネットワークから大量のデータを収集するプロジェクトに取り組んでいます。Postgresの大きなテーブルを重複してチェックする効率的な挿入
CREATE TABLE public.readings (
id INTEGER PRIMARY KEY NOT NULL DEFAULT nextval('readings_id_seq'::regclass),
created TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(),
timestamp TIMESTAMP WITHOUT TIME ZONE NOT NULL,
modem_serial CHARACTER VARYING(255) NOT NULL,
channel1 INTEGER NOT NULL,
channel2 INTEGER NOT NULL,
signal_strength INTEGER,
battery INTEGER,
excluded BOOLEAN NOT NULL DEFAULT false
);
CREATE UNIQUE INDEX _timestamp_modemserial_uc ON readings USING BTREE (timestamp, modem_serial);
CREATE INDEX ix_readings_timestamp ON readings USING BTREE (timestamp);
CREATE INDEX ix_readings_modem_serial ON readings USING BTREE (modem_serial);
それは我々が同じタイムスタンプと同じモデムから2つの測定値、したがって、一意のインデックスを持っていることはありませんシステムの整合性のために重要です。私たちはこのようになりますテーブル「測定値」を持っています。
現時点で私たちの課題は、読書を挿入する演奏方法を見つけることです。過去のデータを取り込む際には、何百万行も挿入する必要があります。既存のデータに1億分の1を加えた値を加算すると、これはかなり遅くなります。
私たちの現在のアプローチは、10,000回の読み込みのバッチを一時的な読み込みテーブルにインポートすることです。これは、本質的に読み取りのコピーされていないコピーです。私たちは、その後、メインテーブルにそれをマージし、重複を削除するには、以下のSQLを実行します。
INSERT INTO readings (created, timestamp, modem_serial, channel1, channel2, signal_strength, battery)
SELECT DISTINCT ON (timestamp, modem_serial) created, timestamp, modem_serial, channel1, channel2, signal_strength, battery
FROM temporary_readings
WHERE NOT EXISTS(
SELECT * FROM readings
WHERE timestamp=temporary_readings.timestamp
AND modem_serial=temporary_readings.modem_serial
)
ORDER BY timestamp, modem_serial ASC;
これはうまく動作しますが、挿入するために〜万行ブロックごとに20秒かかります。私の質問は二重です:
- これは問題に近づく最も良い方法ですか?私はこれらの種類のパフォーマンス要求を持つプロジェクトには比較的新しいので、より良いソリューションがあるかどうかを知りたいと思っています。
- 挿入プロセスのスピードアップにはどのような手順が必要ですか?事前に
ありがとう!
あなたのユースケースについて詳しく説明できますか?リアルタイムで読み上げをデデュープする必要があるのですか、アナリティクス用のウェアハウスを構築していますか? – wrschneider
'temporary_readings'テーブルに構造や制約(PKやUNIQUE制約など)がありますか? – wildplasser