2025年9月25日: PostgreSQL 18 釋出!
支援版本: 當前 (18) / 17 / 16 / 15 / 14 / 13
開發版本: devel
不支援的版本: 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3

F.38. postgres_fdw — 訪問儲存在外部 PostgreSQL 伺服器中的資料 #

postgres_fdw 模組提供了外部資料包裝器 postgres_fdw,可用於訪問儲存在外部 PostgreSQL 伺服器中的資料。

此模組提供的功能與較舊的 dblink 模組的功能有很大重疊。但 postgres_fdw 提供了更透明、更符合標準語法的訪問遠端表的方式,並且在許多情況下可以提供更好的效能。

為使用 postgres_fdw 進行遠端訪問做準備

  1. 使用 CREATE EXTENSION 安裝 postgres_fdw 擴充套件。

  2. 建立一個外部伺服器物件,使用 CREATE SERVER,代表您想連線的每個遠端資料庫。將連線資訊(除 userpassword 外)指定為伺服器物件的選項。

  3. 建立一個使用者對映,使用 CREATE USER MAPPING,為每個允許訪問每個外部伺服器的資料庫使用者建立。將要使用的遠端使用者名稱和密碼指定為使用者對映的 userpassword 選項。

  4. 建立一個外部表,使用 CREATE FOREIGN TABLEIMPORT FOREIGN SCHEMA,為每個您想訪問的遠端表建立。外部表的列必須匹配引用的遠端表。但是,如果您將正確的遠端名稱指定為外部表物件的選項,則可以使用與遠端表不同的表名和/或列名。

現在您只需從外部表 SELECT 即可訪問其底層遠端表中儲存的資料。您還可以使用 INSERTUPDATEDELETECOPYTRUNCATE 修改遠端表。(當然,您在使用者對映中指定的遠端使用者必須具有執行這些操作的許可權。)

請注意,當訪問或修改遠端表時,在 SELECTUPDATEDELETETRUNCATE 中指定的 ONLY 選項無效。

請注意,postgres_fdw 目前不支援帶有 ON CONFLICT DO UPDATE 子句的 INSERT 語句。但是,ON CONFLICT DO NOTHING 子句是支援的,前提是省略了唯一索引推斷規範。另請注意,postgres_fdw 支援對分割槽表執行的 UPDATE 語句觸發的行移動,但目前不處理將移動的行插入到的遠端分割槽也是同一命令中其他位置更新的目標分割槽的情況。

通常建議將外部表的列宣告為與遠端表中的相應列具有完全相同的資料型別,如果適用,還需要宣告相同排序規則。雖然 postgres_fdw 目前在必要時執行資料型別轉換時相當寬容,但當型別或排序規則不匹配時,由於遠端伺服器對查詢條件的解釋可能與本地伺服器不同,可能會出現令人驚訝的語義異常。

請注意,外部表宣告的列數可以少於其底層遠端表,或者列順序可以不同。列與遠端表的匹配是按名稱進行的,而不是按位置。

F.38.1. postgres_fdw 的 FDW 選項 #

F.38.1.1. 連線選項 #

使用 postgres_fdw 外部資料包裝器的外部伺服器可以具有 libpq 在連線字串中接受的相同選項,如 第 32.1.2 節中所述,但這些選項不允許或有特殊處理

  • userpasswordsslpassword(請在使用者對映中指定這些,或使用服務檔案)

  • client_encoding(此項會自動從本地伺服器編碼設定)

  • application_name - 此項可以出現在連線和 postgres_fdw.application_name一個或兩個 中。如果兩者都存在,則 postgres_fdw.application_name 會覆蓋連線設定。與 libpq 不同,postgres_fdw 允許 application_name 包含 轉義序列。有關詳細資訊,請參見 postgres_fdw.application_name

  • fallback_application_name(始終設定為 postgres_fdw

  • sslkeysslcert - 這些選項可以出現在連線和使用者對映的 一個或兩個 中。如果兩者都存在,則使用者對映設定會覆蓋連線設定。

只有超級使用者才能建立或修改具有 sslcertsslkey 設定的使用者對映。

非超級使用者可以使用密碼認證或 GSSAPI 委派憑證連線到外部伺服器,因此對於需要密碼認證的使用者對映,請指定 password 選項。

超級使用者可以透過設定使用者對映選項 password_required 'false' 來在每個使用者對映的基礎上覆蓋此檢查,例如:

ALTER USER MAPPING FOR some_non_superuser SERVER loopback_nopw
OPTIONS (ADD password_required 'false');

為防止特權不足的使用者利用執行 postgres 伺服器的 unix 使用者的認證許可權來提升到超級使用者許可權,只有超級使用者才能在使用者對映上設定此選項。

需要謹慎操作,以確保這不會讓對映的使用者能夠以超級使用者的身份連線到對映的資料庫,如 CVE-2007-3278 和 CVE-2007-6601 所示。不要在 public 角色上設定 password_required=false。請記住,對映的使用者可能會利用執行 postgres 伺服器的系統使用者的 unix 主目錄中的任何客戶端證書、.pgpass.pg_service.conf 等。他們還可以使用 peerident 認證模式授予的任何信任關係。(有關查詢主目錄的詳細資訊,請參見 第 32.16 節。)

F.38.1.2. 物件名稱選項 #

這些選項可用於控制傳送到遠端 PostgreSQL 伺服器的 SQL 語句中使用的名稱。當使用與底層遠端表名稱不同的名稱建立外部表時,需要這些選項。

schema_name (string)

此選項可用於外部表,指定在遠端伺服器上使用的外部表的模式名稱。如果省略此選項,則使用外部表的模式名稱。

table_name (string)

此選項可用於外部表,指定在遠端伺服器上使用的外部表的表名。如果省略此選項,則使用外部表的名稱。

column_name (string)

此選項可用於外部表的列,指定在遠端伺服器上使用的列名。如果省略此選項,則使用列名。

F.38.1.3. 成本估算選項 #

postgres_fdw 透過在遠端伺服器上執行查詢來檢索遠端資料,因此理想情況下,掃描外部表的估計成本應與在遠端伺服器上執行的成本相同,再加上一些通訊開銷。最可靠的估算方法是詢問遠端伺服器,然後新增一些開銷——但對於簡單查詢,為了獲得成本估算而進行額外的遠端查詢可能不值得。因此,postgres_fdw 提供了以下選項來控制成本估算的方式。

use_remote_estimate (boolean)

此選項可用於外部表或外部伺服器,控制 postgres_fdw 是否發出遠端 EXPLAIN 命令來獲取成本估算。對於外部表的設定會覆蓋其伺服器的任何設定,但僅限於該表。預設為 false

fdw_startup_cost (floating point)

此選項可用於外部伺服器,是一個浮點值,將加到該伺服器上的任何外部表掃描的估算啟動成本上。這代表了建立連線、在遠端端解析和規劃查詢等方面的額外開銷。預設值為 100

fdw_tuple_cost (floating point)

此選項可用於外部伺服器,是一個浮點值,用作該伺服器上外部表掃描的每行額外成本。這代表了伺服器之間資料傳輸的額外開銷。您可以增加或減少此數字以反映到遠端伺服器的網路延遲較高或較低。預設值為 0.2

use_remote_estimate 為 true 時,postgres_fdw 從遠端伺服器獲取行數和成本估算,然後將 fdw_startup_costfdw_tuple_cost 加到成本估算中。當 use_remote_estimate 為 false 時,postgres_fdw 進行本地行數和成本估算,然後將 fdw_startup_costfdw_tuple_cost 加到成本估算中。除非本地有遠端表統計資訊的本地副本,否則此本地估算不太可能非常準確。在外部表上執行 ANALYZE 是更新本地統計資訊的途徑;這將掃描遠端表,然後計算並存儲統計資訊,就好像該表是本地表一樣。保留本地統計資訊可以減少遠端表每個查詢的規劃開銷——但如果遠端表經常更新,本地統計資訊將很快過時。

以下選項控制這種 ANALYZE 操作的行為

analyze_sampling (string)

此選項可用於外部表或外部伺服器,決定 ANALYZE 在外部表上是取樣遠端端的資料,還是讀取並傳輸所有資料並在本地進行取樣。支援的值為 offrandomsystembernoulliautooff 停用遠端取樣,因此所有資料都將在本地傳輸和取樣。random 使用 random() 函式選擇返回的行進行遠端取樣,而 systembernoulli 則依賴於內建的這些名稱的 TABLESAMPLE 方法。random 在所有遠端伺服器版本上都有效,而 TABLESAMPLE 僅自 9.5 起支援。auto(預設值)會自動選擇推薦的取樣方法;目前意味著根據遠端伺服器版本選擇 bernoullirandom

F.38.1.4. 遠端執行選項 #

預設情況下,只有使用內建運算子和函式的 WHERE 子句才會被考慮在遠端伺服器上執行。涉及非內建函式的子句在獲取行後在本地檢查。如果遠端伺服器上存在這些函式,並且可以依賴它們產生與本地相同的查詢結果,那麼將這些 WHERE 子句傳送到遠端執行可以提高效能。此行為可以透過以下選項控制

extensions (string)

此選項是一個逗號分隔的列表,包含本地和遠端伺服器上已安裝且版本相容的 PostgreSQL 擴充套件的名稱。屬於列出的擴充套件且不可變的函式和運算子將被視為可以傳送到遠端伺服器。此選項只能為外部伺服器指定,不能為每個表指定。

使用 extensions 選項時,使用者有責任 確保列出的擴充套件在本地和遠端伺服器上都存在且行為相同。否則,遠端查詢可能會失敗或行為異常。

fetch_size (integer)

此選項指定 postgres_fdw 在每次獲取操作中應獲取的行數。它可以為外部表或外部伺服器指定。在表上指定的選項會覆蓋為伺服器指定的選項。預設值為 100

batch_size (integer)

此選項指定 postgres_fdw 在每次插入操作中應插入的行數。它可以為外部表或外部伺服器指定。在表上指定的選項會覆蓋為伺服器指定的選項。預設值為 1

請注意,postgres_fdw 一次實際插入的行數取決於列數和提供的 batch_size 值。批處理作為單個查詢執行,libpq 協議(postgres_fdw 使用該協議連線到遠端伺服器)將單個查詢中的引數數量限制為 65535。當列數 * batch_size 超過限制時,batch_size 將被調整以避免錯誤。

此選項也適用於複製到外部表的情況。在這種情況下,postgres_fdw 一次複製的實際行數以類似插入情況的方式確定,但由於 COPY 命令的實現限制,最多限制為 1000 行。

F.38.1.5. 非同步執行選項 #

postgres_fdw 支援非同步執行,它併發執行 Append 節點中的多個部分,而不是序列執行,以提高效能。此執行可以透過以下選項控制

async_capable (boolean)

此選項控制 postgres_fdw 是否允許併發掃描外部表以進行非同步執行。它可以為外部表或外部伺服器指定。表級選項會覆蓋伺服器級選項。預設值為 false

為確保從外部伺服器返回的資料一致,postgres_fdw 將只為一個給定的外部伺服器開啟一個連線,並按順序在該伺服器上執行所有查詢,即使有多個外部表涉及,除非這些表受不同的使用者對映管轄。在這種情況下,停用此選項以消除執行非同步查詢的開銷可能會更有效。

非同步執行即使在 Append 節點包含同步執行的子計劃和非同步執行的子計劃時也會應用。在這種情況下,如果非同步子計劃是使用 postgres_fdw 處理的,則非同步子計劃中的元組要到至少一個同步子計劃返回所有元組之後才會返回,因為該子計劃會在非同步子計劃等待外部伺服器的非同步查詢結果時執行。此行為可能會在未來的版本中更改。

F.38.1.6. 事務管理選項 #

如事務管理部分所述,在 postgres_fdw 中,事務透過建立相應的遠端事務來管理,子事務透過建立相應的遠端子事務來管理。噹噹前本地事務涉及多個遠端事務時,預設情況下,當本地事務提交或中止時,postgres_fdw 會序列地提交或中止這些遠端事務。噹噹前本地子事務涉及多個遠端子事務時,預設情況下,當本地子事務提交或中止時,postgres_fdw 會序列地提交或中止這些遠端子事務。使用以下選項可以提高效能

parallel_commit (boolean)

此選項控制當本地事務提交時,postgres_fdw 是否並行提交在外部伺服器上開啟的遠端事務。此設定也適用於遠端和本地子事務。此選項只能為外部伺服器指定,不能為每個表指定。預設為 false

parallel_abort (boolean)

此選項控制當本地事務中止時,postgres_fdw 是否並行中止在外部伺服器上開啟的遠端事務。此設定也適用於遠端和本地子事務。此選項只能為外部伺服器指定,不能為每個表指定。預設為 false

如果多個啟用了這些選項的外部伺服器參與了本地事務,當本地事務提交或中止時,這些外部伺服器上的多個遠端事務會並行提交或中止。

當啟用這些選項時,具有許多遠端事務的外部伺服器在本地事務提交或中止時可能會出現負效能影響。

F.38.1.7. 可更新性選項 #

預設情況下,所有使用 postgres_fdw 的外部表都假定為可更新的。這可以透過以下選項覆蓋

updatable (boolean)

此選項控制 postgres_fdw 是否允許使用 INSERTUPDATEDELETE 命令修改外部表。它可以為外部表或外部伺服器指定。表級選項會覆蓋伺服器級選項。預設值為 true

當然,如果遠端表實際上不可更新,仍然會發生錯誤。此選項的使用主要允許在不查詢遠端伺服器的情況下本地丟擲錯誤。但請注意,postgres_fdw 外部表是否可更新(或不可更新),而無需檢查遠端伺服器。

F.38.1.8. 可截斷性選項 #

預設情況下,所有使用 postgres_fdw 的外部表都假定為可截斷的。這可以透過以下選項覆蓋

truncatable (boolean)

此選項控制 postgres_fdw 是否允許使用 TRUNCATE 命令截斷外部表。它可以為外部表或外部伺服器指定。表級選項會覆蓋伺服器級選項。預設值為 true

當然,如果遠端表實際上不可截斷,仍然會發生錯誤。此選項的使用主要允許在不查詢遠端伺服器的情況下本地丟擲錯誤。

F.38.1.9. 匯入選項 #

postgres_fdw 能夠使用 IMPORT FOREIGN SCHEMA 匯入外部表定義。此命令在本地伺服器上建立與遠端伺服器上存在的表或檢視匹配的外部表定義。如果要匯入的遠端表具有使用者定義資料型別的列,則本地伺服器必須具有同名的相容型別。

可以透過以下選項(在 IMPORT FOREIGN SCHEMA 命令中給出)來自定義匯入行為

import_collate (boolean)

此選項控制是否在從外部伺服器匯入的外部表定義中包含列 COLLATE 選項。預設為 true。如果遠端伺服器具有與本地伺服器不同的排序規則名稱集,則可能需要關閉此選項,如果它執行在不同的作業系統上,這種情況很可能發生。但是,如果您這樣做,匯入的表列的排序規則很可能與底層資料不匹配,從而導致異常的查詢行為,存在非常嚴重的風險。

即使將此引數設定為 true,匯入排序規則是遠端伺服器預設值的列也可能存在風險。它們將以 COLLATE "default" 匯入,這將選擇本地伺服器的預設排序規則,這可能不同。

import_default (boolean)

此選項控制是否在從外部伺服器匯入的外部表定義中包含列 DEFAULT 表示式。預設為 false。如果啟用此選項,請注意預設值在本地伺服器上的計算方式可能與在遠端伺服器上的不同;nextval() 是一個常見的問題來源。IMPORT 將完全失敗,如果匯入的預設表示式使用本地不存在的函式或運算子。

import_generated (boolean)

此選項控制是否在從外部伺服器匯入的外部表定義中包含列 GENERATED 表示式。預設為 trueIMPORT 將完全失敗,如果匯入的生成表示式使用本地不存在的函式或運算子。

import_not_null (boolean)

此選項控制是否在從外部伺服器匯入的外部表定義中包含列 NOT NULL 約束。預設為 true

請注意,除 NOT NULL 之外的其他約束永遠不會從遠端表中匯入。雖然 PostgreSQL 支援對外部表設定檢查約束,但沒有自動匯入它們的機制,因為約束表示式在本地和遠端伺服器上的評估方式可能不同。任何這種檢查約束行為的不一致都可能導致難以檢測的查詢最佳化錯誤。因此,如果您想匯入檢查約束,您必須手動執行,並且應該仔細驗證每個約束的語義。有關外部表上檢查約束處理的更多詳細資訊,請參見 CREATE FOREIGN TABLE

作為其他表分割槽的表或外部表僅在 LIMIT TO 子句中顯式指定時才被匯入。否則,它們會自動從 IMPORT FOREIGN SCHEMA 中排除。由於可以透過分割槽層次結構的根節點——分割槽表來訪問所有資料,因此僅匯入分割槽表應該能夠訪問所有資料而無需建立額外的物件。

F.38.1.10. 連線管理選項 #

預設情況下,postgres_fdw 建立的所有到外部伺服器的連線都會在本地會話中保持開啟狀態以便重用。

keep_connections (boolean) #

此選項控制 postgres_fdw 是否保持與外部伺服器的連線開啟,以便後續查詢可以重用它們。它只能為外部伺服器指定。預設值為 on。如果設定為 off,則在每個事務結束時,到此外部伺服器的所有連線都將被丟棄。

use_scram_passthrough (boolean) #

此選項控制 postgres_fdw 是否使用 SCRAM 旁路認證連線到外部伺服器。使用 SCRAM 旁路認證時,postgres_fdw 使用 SCRAM 雜湊加密的金鑰而不是明文使用者密碼來連線到遠端伺服器。這避免了在 PostgreSQL 系統目錄中儲存明文使用者密碼。

要使用 SCRAM 旁路認證

  • 遠端伺服器必須請求 scram-sha-256 認證方法;否則,連線將失敗。

  • 遠端伺服器可以是支援 SCRAM 的任何 PostgreSQL 版本。僅需要在客戶端(FDW 端)支援 use_scram_passthrough

  • 不使用使用者對映密碼。

  • 執行 postgres_fdw 的伺服器和遠端伺服器必須為 postgres_fdw 用於在外連線伺服器上進行身份驗證的使用者擁有相同的 SCRAM 金鑰(加密密碼)(相同的鹽和迭代次數,而不僅僅是相同的密碼)。

    因此,如果要建立到多個主機的 FDW 連線(例如,用於分割槽外部表/分片),則所有主機必須為涉及的使用者擁有相同的 SCRAM 金鑰。

  • 發起傳出 FDW 連線的 PostgreSQL 例項的當前會話也必須使用 SCRAM 認證進行傳入客戶端連線。(因此是 旁路:SCRAM 必須進出都使用。)這是 SCRAM 協議的技術要求。

F.38.2. 函式 #

postgres_fdw_get_connections( IN check_conn boolean DEFAULT false, OUT server_name text, OUT user_name text, OUT valid boolean, OUT used_in_xact boolean, OUT closed boolean, OUT remote_backend_pid int4) returns setof record

此函式返回有關 postgres_fdw 從本地會話建立到外部伺服器的所有開啟連線的資訊。如果沒有開啟的連線,則不返回任何記錄。

如果將 check_conn 設定為 true,則函式會檢查每個連線的狀態並在 closed 列中顯示結果。此功能目前僅在支援非標準 poll 系統呼叫的 POLLRDHUP 擴充套件的系統上可用,包括 Linux。這有助於檢查事務中使用的所有連線是否仍然開啟。如果任何連線已關閉,則事務將無法成功提交,因此最好在檢測到連線關閉時立即回滾,而不是繼續到最後。如果函式報告 used_in_xactclosed 都為 true 的連線,使用者可以立即回滾事務。

函式用法示例

postgres=# SELECT * FROM postgres_fdw_get_connections(true);
 server_name | user_name | valid | used_in_xact | closed | remote_backend_pid
-------------+-----------+-------+--------------+-----------------------------
 loopback1   | postgres  | t     | t            | f      |            1353340
 loopback2   | public    | t     | t            | f      |            1353120
 loopback3   |           | f     | t            | f      |            1353156

輸出列在 表 F.28 中描述。

表 F.28. postgres_fdw_get_connections 輸出列

型別 描述
server_name text 此連線的外部伺服器名稱。如果伺服器已被刪除但連線保持開啟狀態(即,標記為無效),則此項將為 NULL
user_name text 對映到此連線的外部伺服器的本地使用者名稱稱,如果使用公共對映,則為 public。如果使用者對映已被刪除但連線保持開啟狀態(即,標記為無效),則此項將為 NULL
valid boolean 如果此連線無效,則為 False,表示它在當前事務中使用,但其外部伺服器或使用者對映已被更改或刪除。無效的連線將在事務結束時關閉。否則返回 True。
used_in_xact boolean 如果此連線在當前事務中使用,則為 True。
closed boolean 如果此連線已關閉,則為 True,否則為 False。NULLcheck_conn 設定為 false 或此平臺不支援連線狀態檢查時返回。
remote_backend_pid int4 處理連線的外部伺服器上的遠端後端程序 ID。如果遠端後端已終止且連線已關閉(closed 設定為 true),則仍顯示已終止後端的程序 ID。

postgres_fdw_disconnect(server_name text) returns boolean

此函式丟棄 postgres_fdw 從本地會話建立到具有給定名稱的外部伺服器的開啟連線。請注意,可以使用不同的使用者對映連線到給定伺服器的連線可能不止一個。如果連線在當前本地事務中使用,則它們不會被斷開連線,並會報告警告訊息。如果該函式斷開了至少一個連線,則返回 true,否則返回 false。如果找不到具有給定名稱的外部伺服器,則會報告錯誤。函式用法示例

postgres=# SELECT postgres_fdw_disconnect('loopback1');
 postgres_fdw_disconnect
-------------------------
 t
postgres_fdw_disconnect_all() returns boolean

此函式丟棄 postgres_fdw 從本地會話建立到外部伺服器的所有開啟連線。如果連線在當前本地事務中使用,則它們不會被斷開連線,並會報告警告訊息。如果該函式斷開了至少一個連線,則返回 true,否則返回 false。函式用法示例

postgres=# SELECT postgres_fdw_disconnect_all();
 postgres_fdw_disconnect_all
-----------------------------
 t

F.38.3. 連線管理 #

postgres_fdw 在第一次查詢使用與外部伺服器關聯的外部表時建立到外部伺服器的連線。預設情況下,此連線會保持開啟狀態並在同一會話的後續查詢中重用。此行為可以透過外部伺服器的 keep_connections 選項來控制。如果使用多個使用者身份(使用者對映)訪問外部伺服器,則為每個使用者對映建立一個連線。

更改外部伺服器或使用者對映的定義或刪除它們時,相關的連線會被關閉。但請注意,如果任何連線在當前本地事務中使用,則會保留到事務結束。關閉的連線將在將來的查詢使用外部表時重新建立。

一旦建立了到外部伺服器的連線,預設情況下它會一直保持開啟狀態,直到本地或相應的遠端會話退出。要顯式斷開連線,可以停用外部伺服器的 keep_connections 選項,或者使用 postgres_fdw_disconnectpostgres_fdw_disconnect_all 函式。例如,這些對於關閉不再需要的連線很有用,從而釋放外部伺服器上的連線。

F.38.4. 事務管理 #

在引用外部伺服器上任何遠端表的查詢期間,如果當前本地事務還沒有對應的遠端事務,postgres_fdw 會在遠端伺服器上開啟一個事務。當本地事務提交或中止時,遠端事務也會相應地提交或中止。儲存點也以類似的方式進行管理,透過建立相應的遠端儲存點。

當本地事務具有 SERIALIZABLE 隔離級別時,遠端事務使用 SERIALIZABLE 隔離級別;否則,它使用 REPEATABLE READ 隔離級別。此選擇確保如果查詢在遠端伺服器上執行多次表掃描,它將為所有掃描獲得快照一致的結果。其結果是,單個事務內的連續查詢將從遠端伺服器看到相同的資料,即使遠端伺服器由於其他活動正在進行併發更新。如果本地事務使用 SERIALIZABLEREPEATABLE READ 隔離級別,則可以預期這種行為,但對於 READ COMMITTED 本地事務來說,這可能會令人驚訝。未來的 PostgreSQL 版本可能會修改這些規則。

請注意,postgres_fdw 目前不支援為兩階段提交準備遠端事務。

F.38.5. 遠端查詢最佳化 #

postgres_fdw 嘗試最佳化遠端查詢,以減少從外部伺服器傳輸的資料量。這是透過將查詢 WHERE 子句傳送到遠端伺服器執行,以及不檢索當前查詢不需要的表列來實現的。為減少查詢誤執行的風險,除非 WHERE 子句僅使用內建的或屬於 extensions 選項中列出的擴充套件的資料型別、運算子和函式,否則不會將其傳送到遠端伺服器。此類子句中的運算子和函式也必須是 IMMUTABLE。對於 UPDATEDELETE 查詢,如果不存在不能傳送到遠端伺服器的查詢 WHERE 子句、沒有本地連線、目標表上沒有行級本地 BEFOREAFTER 觸發器或儲存的生成列,以及沒有父檢視的 CHECK OPTION 約束,postgres_fdw 會嘗試透過將整個查詢傳送到遠端伺服器來最佳化查詢執行。在 UPDATE 中,賦值給目標列的表示式必須僅使用內建資料型別、IMMUTABLE 運算子或 IMMUTABLE 函式,以降低查詢誤執行的風險。

postgres_fdw 遇到同一外部伺服器上的外部表之間的連線時,它會將整個連線傳送到外部伺服器,除非出於某種原因它認為單獨獲取每個表的行效率更高,或者除非涉及的表引用受不同的使用者對映管轄。在傳送 JOIN 子句時,它會採取與上述 WHERE 子句相同的預防措施。

實際傳送到遠端伺服器執行的查詢可以使用 EXPLAIN VERBOSE 來檢視。

F.38.6. 遠端查詢執行環境 #

postgres_fdw 開啟的遠端會話中,search_path 引數被設定為僅 pg_catalog,因此只有內建物件在沒有模式限定的情況下可見。這對於透過遠端表上的觸發器或規則在遠端伺服器上執行的函式來說不是問題。例如,如果遠端表實際上是一個檢視,那麼在該檢視中使用的任何函式都將在受限制的搜尋路徑下執行。建議對這些函式中的所有名稱進行模式限定,或者將 SET search_path 選項(參見 CREATE FUNCTION)附加到這些函式上,以建立其預期的搜尋路徑環境。

postgres_fdw 同樣會為各種引數建立遠端會話設定

這些問題不像 search_path 那麼容易出現問題,但如果需要,可以透過函式 SET 選項來處理。

強烈建議透過更改這些引數的會話級設定來覆蓋此行為;這很可能會導致 postgres_fdw 出現故障。

F.38.7. 跨版本相容性 #

postgres_fdw 可與早至 PostgreSQL 8.3 的遠端伺服器一起使用。只讀功能可追溯到 8.1。

然而,一個限制是 postgres_fdw 通常假定不可變的內建函式和運算子可以安全地傳送到遠端伺服器執行,如果它們出現在外部表的 WHERE 子句中。因此,自遠端伺服器釋出以來新增的內建函式可能會被髮送給它執行,從而導致 函式不存在 或類似的錯誤。可以透過重寫查詢來解決此類失敗,例如,將外部表引用嵌入到帶有 OFFSET 0 的子 SELECT 中作為最佳化屏障,並將有問題的函式或運算子放在子 SELECT 之外。

另一個限制是,當在外部表上執行帶有 ON CONFLICT DO NOTHING 子句的 INSERT 語句時,遠端伺服器必須執行 PostgreSQL 9.5 或更高版本,因為早期版本不支援此功能。

F.38.8. 等待事件 #

postgres_fdw 可以在 Extension 等待事件型別下報告以下等待事件

PostgresFdwCleanupResult

等待遠端伺服器上的事務中止。

PostgresFdwConnect

等待建立到遠端伺服器的連線。

PostgresFdwGetResult

等待從遠端伺服器接收查詢結果。

F.38.9. 配置引數 #

postgres_fdw.application_name (string) #

指定 postgres_fdw 建立到外部伺服器的連線時使用的 application_name 配置引數的值。這會覆蓋伺服器物件的 application_name 選項。請注意,此引數的更改不會影響任何現有連線,直到它們被重新建立。

postgres_fdw.application_name 可以是任何長度的字串,甚至包含非 ASCII 字元。但是,當它被傳遞並用作外部伺服器中的 application_name 時,請注意它將被截斷到少於 NAMEDATALEN 個字元。任何非可列印 ASCII 字元都將被替換為 C 風格的十六進位制轉義。有關詳細資訊,請參見 application_name

% 字元開頭 轉義序列,它們會被替換為下面概述的狀態資訊。無法識別的轉義會被忽略。其他字元會原樣複製到應用程式名稱。請注意,不允許在 % 之後和選項之前指定加/減號或數字文字,用於對齊和填充。

轉義 效果
%a 本地伺服器上的應用程式名稱
%c 本地伺服器上的會話 ID(有關詳細資訊,請參見 log_line_prefix
%C 本地伺服器上的叢集名稱(有關詳細資訊,請參見 cluster_name
%u 本地伺服器上的使用者名稱
%d 本地伺服器上的資料庫名稱
%p 本地伺服器後端程序 ID
%% 字面量 %

例如,假設使用者 local_user 從資料庫 local_db 連線到 foreign_db,使用者為 foreign_user,設定 'db=%d, user=%u' 將被替換為 'db=local_db, user=local_user'

F.38.10. 示例 #

以下是使用 postgres_fdw 建立外部表的示例。首先安裝擴充套件

CREATE EXTENSION postgres_fdw;

然後使用 CREATE SERVER 建立外部伺服器。在本例中,我們希望連線到主機 192.83.123.89 上監聽埠 5432PostgreSQL 伺服器。連線到的資料庫在遠端伺服器上名為 foreign_db

CREATE SERVER foreign_server
        FOREIGN DATA WRAPPER postgres_fdw
        OPTIONS (host '192.83.123.89', port '5432', dbname 'foreign_db');

還需要使用 CREATE USER MAPPING 定義使用者對映,以識別將在遠端伺服器上使用的角色。

CREATE USER MAPPING FOR local_user
        SERVER foreign_server
        OPTIONS (user 'foreign_user', password 'password');

現在可以使用 CREATE FOREIGN TABLE 建立外部表。在本例中,我們希望訪問遠端伺服器上名為 some_schema.some_table 的表。其本地名稱將是 foreign_table

CREATE FOREIGN TABLE foreign_table (
        id integer NOT NULL,
        data text
)
        SERVER foreign_server
        OPTIONS (schema_name 'some_schema', table_name 'some_table');

宣告在 CREATE FOREIGN TABLE 中的列的資料型別和其他屬性必須與實際遠端表匹配,這一點至關重要。列名也必須匹配,除非您將 column_name 選項附加到各個列,以顯示它們在遠端伺服器上的命名方式。在許多情況下,使用 IMPORT FOREIGN SCHEMA 比手動構建外部表定義更可取。

F.38.11. 作者 #

Shigeru Hanada

提交更正

如果您在文件中發現任何不正確的內容、與您對特定功能的體驗不符的內容或需要進一步澄清的內容,請使用 此表單 報告文件問題。