加快 Postgresql 手動索引重置?
我正在相互合併數據庫。我遇到的一個問題是兩個數據庫表都具有相同的主鍵(從 1 開始,否則它們是不同的記錄)。
為了解決這個問題,我執行以下(作為虛擬碼):
last=1 for db in databases: ALTER TABLE table1 DROP CONSTRAINT table1_pkey CREATE SEQUENCE temp_seq START last UPDATE table1 SET table1_pk = nextval('temp_seq') ALTER TABLE table1 ADD PRIMARY KEY table1_pk last = nextval('temp_seq') DROP SEQUENCE temp_seq
這會遍歷所有數據庫並從 1 開始重置它們的索引。第一個數據庫的索引為 1-50,第二個為 51-125,第三個為 126-223,依此類推。在此之後,我將它們轉儲並恢復到一個數據庫,但沒有重疊了。
一切正常,除了索引重置部分對於更大的數據庫(許多 GB 的數據)非常慢。我發現 postgres 在每個
UPDATE table1 SET table1_pk = nextval('temp_seq')
. 這使得一切都比以前慢。根據我的理解,這樣做是為了防止事務ID環繞?來自 PostgreSQL 文件:https ://www.postgresql.org/docs/9.3/routine-vacuuming.html#VACUUM-FOR-WRAPAROUNDPostgreSQL 的 MVCC 事務語義依賴於能夠比較事務 ID (XID) 編號:插入 XID 大於目前事務 XID 的行版本是“在未來”並且不應該對目前事務可見。但是由於事務 ID 的大小有限(32 位),長時間執行(超過 40 億個事務)的集群將遭受事務 ID 迴繞:XID 計數器迴繞為零,並且突然之間,在過去似乎在未來——這意味著它們的輸出變得不可見。簡而言之,災難性的數據失去。(實際上數據仍然存在,但如果您無法獲取它,那將是一種冷酷的安慰。)為了避免這種情況,有必要每 20 億次事務至少對每個數據庫中的每個表進行一次清理。
這是正確的原因嗎?有沒有更快的方法來重置主鍵?或者在不失去任何數據的情況下調整吸塵參數?
這些數據庫是否在同一個 Postgres 集群中?
如果是這樣,您可能會考慮使用外部數據包裝器,以創建到每個源數據庫的“連接”並將數據直接插入到新表中:
CREATE EXTENSION POSTGRES_FDW ; CREATE SERVER foreign_db FOREIGN DATA WRAPPER POSTGRES_FDW OPTIONS ( HOST 'host_name' , DBNAME 'database_name' , UPDATABLE 'false' ); CREATE USER MAPPING FOR fred SERVER foreign_db OPTIONS ( USER 'fred', PASSWORD 'password' ); CREATE FOREIGN TABLE foreign_old_table ( ... ) SERVER foreign_db OPTIONS ( TABLE_NAME 'old_table' );
然後; 最後
INSERT INTO new_table ( everything, except, pk ) SELECT ( everything, except, id ) FROM foreign_old_table ;
真空分析不僅僅是為了防止事務環繞。它還更新表統計資訊,確定索引是否需要重建和其他有用的東西。
XID與任何表的主鍵 ID 無關*。*
實際上,您可以(並且可能應該)將一個表中的所有行添加到另一個表中,作為一個事務的一部分,只有一個 XID。分析可能正在執行,因為您正在更新表中的每一行,這構成了一個“大”的變化,足以讓分析進入並在該表周圍進行另一次翻找。
您能否在源數據庫中創建“即時”“更改”主鍵值的視圖,將其 pg_dump 載入到您的單個數據庫中?
create view old_table_dump as select id + base_value, everything, expect, id from old_table ;