Postgresql

為 Postgres 表中的每個使用者創建一行

  • August 23, 2015

我在一個表中有一堆使用者行users,例如:

| id |  name |
|----|-------|
|  1 | Chris |
|  2 | Max   |
|  3 | Steve |

對於這些使用者中的每一個,我想在另一個名為的表中創建一行user_flags

| user_id |  flag  |
|---------|--------|
|       1 | myflag |
|       2 | myflag |
|       3 | myflag |

目前我正在做的是一次分批下載約 100 個使用者,然後INSERT對每批進行批量查詢。但是我認為應該有一個更快的方法。

目標:

  • 盡快插入標誌行
  • 長時間執行的查詢很好,只要在任何地方都沒有表鎖定
  • 這些是實時查詢,因此不能刪除索引
  • 應該能夠輕鬆地執行數百萬使用者行

這可能嗎?我覺得它可能/應該有一些智能功能。

這看起來相當簡單:

INSERT INTO user_flags (user_id, flag)
SELECT u.id, 'myflag'   -- or whatever to write to this field
FROM   users u
LEFT   JOIN user_flags uf ON uf.user_id = u.id
WHERE  uf.user_id IS NULL;  -- to exclude already existing

如何 ..

雖然這很容易受到並發事務的競爭條件的影響,但這應該不是問題,因為您一次不會INSERT在多個事務中執行它。

您可以將操作限制為每次呼叫nLIMIT行,例如 100000,只需 append ,可能與ORDER BY

...
ORDER  BY u.id
LIMIT  100000;

重複查詢,直到找到 < 100000 行,在單獨的事務中釋放鎖。通常,即使有數百萬行,您也會在一個命令中完成所有操作。

我建議FOREIGN KEY強制執行參照完整性的約束——如果你還沒有的話。

ALTER TABLE user_flags
 ADD CONSTRAINT user_flags_user_id_fkey FOREIGN KEY (user_id)
 REFERENCES users(id) ON UPDATE CASCADE ON DELETE CASCADE;

以及使 1:1 關係完整的UNIQUEPRIMARY KEY約束。user_flags.user_id

引用自:https://dba.stackexchange.com/questions/111802