[英]PostgreSQL LOGGED and UNLOGGED table performance comparison with LOCK TABLE usage
[英]PostgreSQL Table Comparison
我有一張桌子:
CREATE TABLE my_schema.my_data
(
id character varying COLLATE pg_catalog."default" NOT NULL,
name character varying COLLATE pg_catalog."default" NOT NULL,
length numeric(6,4),
width numeric(6,4),
rp numeric(4,2),
CONSTRAINT id_pkey PRIMARY KEY (id)
);
和一個臨時表:
CREATE TEMPORARY TABLE new_data (LIKE my_schema.my_data);
然后用my_data表中存在的較新版本的數據集填充臨時表。
我試圖識別臨時表中的記錄,這些記錄具有與my_data表中的現有記錄相同的主鍵,但是具有至少一個其他不同的值。
我當前的方法是運行類似於此示例的查詢:
SELECT temp.id
FROM (SELECT * FROM my_schema.my_data WHERE my_data.id IN ('X2025','X8716','X4091','X2443','X8922','X5929','X3016','X3036','X4829','X9578')) AS orig
RIGHT JOIN (SELECT * FROM pg_temp.new_data WHERE new_data.id IN ('X2025','X8716','X4091','X2443','X8922','X5929','X3016','X3036','X4829','X9578')) AS temp
ON (orig.id = temp.id OR (orig.id IS NULL AND temp.id IS NULL))
AND (orig.name = temp.name OR (orig.name IS NULL AND temp.name IS NULL))
AND (orig.length = temp.length OR (orig.length IS NULL and temp.length IS NULL))
AND (orig.width = temp.width OR (orig.width IS NULL and temp.width IS NULL))
AND (orig.rp = temp.rp OR (orig.rp IS NULL and temp.rp IS NULL))
WHERE orig.id IS NULL;
這似乎效率很低,而且在有更多列的情況下,在較大的表上我看不到很好的響應時間,而且我正在遍歷約10,000條記錄的批處理。
有什么建議可以更有效地識別不同的記錄?
更新:
我有一個定期刷新的數據集。 不幸的是,我每次都獲得完整的數據集,而不僅僅是新的或更新的記錄。 (我將在將來修復此過程。)目前,我只想更新表以匹配每天的最新數據。 我通過一個過程來處理這些比較和更新,但是速度非常慢。 我的數據庫表包含import_date和Modifyed_date列,這些列當前正在使用觸發器填充。 通過觸發器,每個INSERT語句都將current_date用作這些記錄的import_date和Modifyed_date。 此外,通過更新前的觸發器將Modifyed_date設置為current_date。 因此,我只想更新在最近一次數據提取中實際經歷過數據更改的記錄。 否則,modified_date列將變得毫無用處,因為我將無法確定該記錄的值最近的更改時間。
電流表:ORIG
(實際表包含大約一百萬條記錄)
| import_date | 修改日期 | id | 名稱 | 長度 寬度 rp |
| 2018-08-17 | 2018-08-17 | 87 | 藍色 | 12.0200 | 8.0503 | 1.82 |
| 2018-08-17 | 2018-08-17 | 88 | 紅色| 11.0870 | 2.0923 | 1.72 |
| 2018-08-17 | 2018-08-17 | 89 | 粉紅色| 15.0870 | 7.9963 | 0.95 |
臨時表:TEMP
(還包含大約一百萬條記錄。將包含當前表中存在的所有主鍵(id列),但也可能包含新的主鍵。)
| import_date | 修改日期 | id | 名稱 | 長度 寬度 rp |
| NULL | NULL | 87 | 藍綠色 12.0200 | 8.0503 | 1.82 |
| NULL | NULL | 88 | 紅色| 11.0870 | 2.0923 | 1.72 |
| NULL | NULL | 89 | 粉紅色| 15.0870 | 7.9963 | 0.95 |
使用上面的示例數據,我希望僅更新第一條記錄,即ID 87。 之后,我的表將如下所示:
| import_date | 修改日期 | id | 名稱 | 長度 寬度 rp |
| 2018-08-17 | 2018-09-12 | 87 | 藍綠色 12.0200 | 8.0503 | 1.82 |
| 2018-08-17 | 2018-08-17 | 88 | 紅色| 11.0870 | 2.0923 | 1.72 |
| 2018-08-17 | 2018-08-17 | 89 | 粉紅色| 15.0870 | 7.9963 | 0.95 |
我的工作方法:我更新了Modifyddate觸發函數,以識別何時需要新的修改日期:
CREATE FUNCTION my_schema.update_mod_date()
RETURNS trigger
LANGUAGE 'plpgsql'
COST 100
VOLATILE NOT LEAKPROOF
AS $BODY$
DECLARE
BEGIN
IF tg_op = 'INSERT' THEN
NEW.modified_date := current_date;
ELSIF tg_op = 'UPDATE' THEN
IF NEW.name IS DISTINCT FROM OLD.name
OR NEW.length IS DISTINCT FROM OLD.length
OR NEW.width IS DISTINCT FROM OLD.width
OR NEW.rp IS DISTINCT FROM OLD.rp THEN
NEW.modified_date := current_date;
ELSE
NEW.modified_date := OLD.modified_date;
END IF;
END IF;
RETURN NEW;
END;
$BODY$;
然后,我可以使用@EvanCarroll提出的原始解決方案:
BEGIN;
INSERT INTO my_schema.my_data (SELECT * FROM pg_temp.new_data)
ON CONFLICT (id) DO UPDATE SET modified_date=NULL, id=EXCLUDED.id,
name=EXCLUDED.name, length=EXCLUDED.length, width=EXCLUDED.width,
rp=EXCLUDED.rp;
COMMIT;
這樣可以確保只有在該行中的其他值之一發生更改時,才會修改Modifyed_date。
如何加入PK,然后僅選擇記錄的其余部分有所不同的記錄,例如:
SELECT
new_data.*
FROM
my_data
INNER JOIN
new_data
ON (my_data.id = new_data.id) -- Same PK
AND (ROW(my_data.*) IS DISTINCT FROM ROW(new_data.*)) -- Any difference in other fields
這將從new_data
表中返回id
與my_data
中的記錄匹配的記錄,但其他任何字段都不匹配。
文檔: https : //www.postgresql.org/docs/current/static/functions-comparisons.html#ROW-WISE-COMPARISON
@EvanCarroll是的,最終目標是使用新的數據集更新原始表。 – 41分鍾前Nathan Scheiderer
然后,您不想這樣做。 您想改為使用INSERT ... ON CONFLICT DO UPDATE
。 這就是您在PostgreSQL中進行增補的方式。
如果你有一排像modified_time
,你只需要在該行被更新的更新,都將其與觸發處理。 這樣 。 然后,您只需像下面這樣寫,
INSERT INTO foo
SELECT *
FROM bar
WHERE NOT EXISTS (
SELECT 1
FROM foo
WHERE foo.x = bar.x
AND NOT foo.whatever = bar.whatever
);
現在,它不會接受該行更新,除非whatever
是對於每個不同的x
。 理想情況下,盡管您不會這樣做。 如果行必須是唯一的whatever
我想補充一點,到索引中。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.