如何找出排除約束應該使用什麼運算符類和訪問方法?
最初的目標:創建一個約束以確保特定 Postgres 表中只存在不重疊的子網。
通過仔細閱讀文件,我可以做到這一點:
create table subnets ( subnet cidr, exclude (subnet with &&) );
但這不起作用。它產生了難以理解的資訊:
ERROR: operator &&(inet,inet) is not a member of operator family "network_ops" DETAIL: The exclusion operator must be related to the index operator class for the constraint.
儘管閱讀了有關運算符類和索引以及索引類型的文件部分,但我仍然覺得我錯過了一個被認為是理所當然的整個解釋部分。我仍然不知道什麼是操作員類,真的,也不是操作員家族。
我確實在郵件列表上找到了一個程式碼片段,該程式碼片段導致以下工作程式碼:
create table subnets ( subnet cidr, exclude using gist (subnet inet_ops with &&) );
但我無法真正理解“使用要點”的用途,也無法真正理解“inet_ops”的用途。
我知道“使用要點”與索引類型有關。我知道索引是為“唯一”約束自動創建的,我猜也可能為“排除”約束自動創建索引。 關於“操作員類”的唯一文件都與*索引有關,*而不是約束。
對於我想要排除約束的這個或未來的查詢,我如何確定應該指定什麼運算符類和訪問方法才能使約束起作用?
請注意,即使手頭有工作程式碼,我也無法找到為什麼它是“gist”而不是其他東西,以及為什麼它是“inet_ops”而不是“network_ops”或什麼都沒有。
\doS
並且操作員類文件中列出的查詢令人費解。我產生的另一個錯誤也令人費解:
vagrant=# create table subnets ( subnet cidr, exclude using gist (subnet with &&) ); ERROR: data type cidr has no default operator class for access method "gist" HINT: You must specify an operator class for the index or define a default operator class for the data type.
(這個問題的前提是我不應該求助於複製和粘貼咒語;徹底審查文件並仔細閱讀錯誤消息應該可以讓我解決問題。對於 Postgres,這在以前一直是正確的。)
PostgreSQL 索引由兩部分組成,從介面擴展到索引的文件
- 索引方法(訪問方法),對於那些你正在談論的 brin、btree、gin、gist、hash、sp-gist(你可以
\dA+
在 psql 中看到這個。)- 操作員類
GIST 是索引方法。為什麼需要 GIST 或 SP-GIST,
EXCLUSION CONSTRAINTS
請參閱這篇文章。您需要的運算符類inet_ops
是. 您遇到的問題是 forcidr
並且inet
提供了兩個 GIST 運算符類,而錯誤的是 default,
- 運算符類
gist_cidr_ops
是預設值。它是“附加提供的模組”的一部分,大多數發行版將其打包為-contrib
. 它由btree_gist
擴展提供(源)- 運算符類
inet_ops
是核心,而不是預設值。你怎麼會知道這個?你可能不會。至於訪問類型,祝你好運。與 PostgreSQL 一起分發的文件本身在這裡非常缺乏,儘管他們確實涉及到這一點,
由於歷史原因,
inet_ops
操作符類不是類型inet
和的預設類cidr
。要使用它,請在 中提及類名CREATE INDEX
,例如CREATE INDEX ON my_table USING GIST (my_inet_column inet_ops);
您可以做的最好的事情是送出一個文件更新檔到
btree_gist
可能也應該記錄的地方。