Postgresql

如何找出排除約束應該使用什麼運算符類和訪問方法?

  • May 4, 2018

最初的目標:創建一個約束以確保特定 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可能應該記錄的地方。

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