Postgresql
為什麼 PostgreSQL FDW 為這個點查詢與多個後端伺服器通信?
我已經使用下表設置了一個 PostgreSQL FDW 伺服器,由
user_id
四個以上的伺服器分片:CREATE TABLE my_big_table ( user_id bigint NOT NULL, serial bigint NOT NULL, -- external, incrementing only some_object_id bigint NOT NULL, timestamp_ns bigint NOT NULL, object_type smallint NOT NULL, other_type smallint NOT NULL, data bytea ) PARTITION BY LIST (mod(user_id, 4)) ;
CREATE SERVER shardA FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host '192.168.200.11', port '5432', dbname 'postgres', fetch_size '10000'); . . . CREATE SERVER shardD FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host '192.168.200.14', port '5432', dbname 'postgres', fetch_size '10000');
create foreign table my_big_table_mod4_s0 partition of my_big_table for values in (0) server shardA OPTIONS (table_name 'my_big_table_mod4_s0'); . . . create foreign table my_big_table_mod4_s3 partition of my_big_table for values in (3) server shardD OPTIONS (table_name 'my_big_table_mod4_s3');
給定一個單一的查詢
user_id
,我希望 FDW 基於簡單的分區修剪選擇一個後端,但explain
顯示對所有四台伺服器的外部表掃描……我如何提示 FDW 更聰明?
PostgreSQL 缺乏對它需要聲明的“mod”函式的洞察力,這
user_id=97
也意味著mod(user_id,4)=1
. 如果您手動提供該見解,它可能會尊重它:WHERE user_id=$1 and mod(user_id,4)=mod($1,4)
這與FDW無關。如果所有分區/表都是本地的,那麼答案將保持不變。
您可以使用雜湊分區,然後它會自動生成洞察力。
這是由於在父表上的列表分區中使用了表達式,並且 PosgreSQL 只能對列表分區中的簡單相等檢查執行修剪,如文件中所述:
保持分區約束簡單,否則規劃器可能無法證明可能不需要訪問子表。對列表分區使用簡單的相等條件,或者對范圍分區使用簡單的範圍測試,如前面的範例所示。一個好的經驗法則是分區約束應該只包含分區列與使用 B-tree-indexable 運算符的常量的比較,因為分區鍵中只允許 B-tree-indexable 列。
為了解決這個問題,這裡有一個想法:而不是
PARTITION BY LIST (mod(user_id, 4))
, dopartition by hash(user_id)
然後在分區上:FOR VALUES WITH (MODULUS 4, REMAINDER 0) server shardA
.然後,PostgreSQL FDW 將按預期實際修剪分區。
但是,數據不會按值的實際模數分佈
user_id
,而是基於值的散列的模數。由於各種原因(例如,已經以非散列方式分發的 TB 級數據),這可能是不可接受的。