Postgresql

加快 Postgresql 手動索引重置?

  • June 17, 2019

我正在相互合併數據庫。我遇到的一個問題是兩個數據庫表都具有相同的主鍵(從 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-WRAPAROUND

PostgreSQL 的 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 ; 

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