我目前正在從一個無線調制解調器網絡中收集非常大量數據的項目。我們有一個表「解讀」,看起來像這樣:在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);
這對於那些我們從來沒有從同一個調制解調器兩個讀數相同的時間戳,因此唯一索引系統的完整性重要。
我們目前的挑戰是找到插入讀數的高性能方式。在我們引入歷史數據時,我們經常需要插入數百萬行,而當增加到現有基數1億以上的讀數時,這可能會變得緩慢。
我們目前的方法是將批量10,000讀數導入到temporary_readings表格中,該表格基本上是未讀索引的副本。然後,我們運行下面的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;
這種運作良好,但需要每〜10,000行的塊20秒內插入。我的問題是雙重的:
- 這是解決問題的最佳方法嗎?對於有這些性能要求的項目,我相對較新,所以我很想知道是否有更好的解決方案。
- 我可以採取哪些步驟來加速插入過程?
在此先感謝!
您能更詳細地描述您的使用案例嗎?您是否需要實時重複讀取數據,或者您是否正在構建分析倉庫? – wrschneider
'temporary_readings'表是否有任何結構或約束(例如PK或UNIQUE約束)? – wildplasser