btree_gist提供了 GiST 索引操作符类,可为以下数据类型实现与 B-树等价的行为: int2, int4, int8, float4, float8, numeric, timestamp with time zone, timestamp without time zone, time with time zone, time without time zone, date, interval, oid, money, char, varchar, text, bytea, bit, varbit, macaddr, macaddr8, inet, cidr, uuid, bool,以及所有enum类型。
一般来说,这些操作符类的性能不会优于对应的标准 B-树索引方法,而且它们缺少标准 B-树实现的一项主要特性:强制唯一性的能力。不过,正如下文所述,它们提供了一些 B-树索引所不具备的其他特性。另外,当需要多列 GiST 索引,而其中某些列的数据类型只能用 GiST 建立索引、其他列只是简单数据类型时,这些操作符类就很有用。最后,这些操作符类对于 GiST 测试以及作为开发其他 GiST 操作符类的基础也很有用。
除典型的 B-树搜索操作符之外,btree_gist还为<>(“不等于”)提供索引支持。这在与下文描述的排他约束结合使用时可能很有用。
此外,对于那些具有自然距离度量的数据类型,btree_gist定义了距离操作符<->,并为使用该操作符的最近邻搜索提供 GiST 索引支持。为以下类型提供了距离操作符:int2、int4、int8、float4、 float8、timestamp with time zone、 timestamp without time zone、 time without time zone、date、interval、 oid和money。
默认情况下,btree_gist会在sorted模式下使用sortsupport构建GiST索引。这通常会显著加快索引构建速度。创建索引时,仍然可以通过使用buffering参数回退到缓冲构建策略。
这个模块被认为是“受信任的”,也就是说,它可以由在当前数据库上具有CREATE权限的非超级用户安装。
一个使用btree_gist代替btree的简单示例:
CREATE TABLE test (a int4); -- create index CREATE INDEX testidx ON test USING GIST (a); -- query SELECT * FROM test WHERE a < 10; -- nearest-neighbor search: find the ten entries closest to "42" SELECT *, a <-> 42 AS dist FROM test ORDER BY a <-> 42 LIMIT 10;
使用排他约束来强制执行这样一条规则:动物园中的一个笼子只能容纳一种动物:
=> CREATE TABLE zoo ( cage INTEGER, animal TEXT, EXCLUDE USING GIST (cage WITH =, animal WITH <>) ); => INSERT INTO zoo VALUES(123, 'zebra'); INSERT 0 1 => INSERT INTO zoo VALUES(123, 'zebra'); INSERT 0 1 => INSERT INTO zoo VALUES(123, 'lion'); ERROR: conflicting key value violates exclusion constraint "zoo_cage_animal_excl" DETAIL: Key (cage, animal)=(123, lion) conflicts with existing key (cage, animal)=(123, zebra). => INSERT INTO zoo VALUES(124, 'lion'); INSERT 0 1
btree_gist 在 inet/cidr 列上的索引 #btree_gist 提供的 gist_inet_ops 和 gist_cidr_ops 操作符类已被证明不可靠:由于创建索引项时使用了近似值,索引搜索可能无法找到相关行。除非重新定义使用这些操作符类的索引内容,否则这一问题无法修复。因此,这些操作符类将被弃用,转而推荐使用内置的 GiST inet_ops 操作符类,因为它没有这个设计缺陷。
第一步,PostgreSQL 19 版本会从 gist_inet_ops 和 gist_cidr_ops 上移除默认操作符类标记,改为把 inet_ops 标记为 inet 和 cidr 列的默认操作符类。这会在大多数场景中透明地用 inet_ops 替换掉这些有缺陷的操作符类。若确有必要,仍然可以通过显式指定要使用的操作符类来创建使用这些有缺陷操作符类的索引;例如
CREATE TABLE mytable (addr inet); CREATE INDEX dubious_index ON mytable USING GIST (addr gist_inet_ops);
不过,由于实现上的限制,pg_upgrade 无法处理这一变更。如果它被要求升级一个包含 gist_inet_ops 或 gist_cidr_ops 索引的 v19 之前数据库,pg_upgrade 会失败,并提示你在升级之前替换这些索引。大致会像这样:
CREATE INDEX good_index ON mytable USING GIST (addr inet_ops); DROP INDEX bad_index;
Teodor Sigaev(<teodor@stack.net>)、 Oleg Bartunov(<oleg@sai.msu.su>)、 Janko Richter(<jankorichter@yahoo.de>)和 Paul Jungwirth(<pj@illuminatedcomputing.com>)。更多信息见 http://www.sai.msu.su/~megera/postgres/gist/。