PostgreSQL

关注公众号 jb51net

关闭
首页 > 数据库 > PostgreSQL > PostgreSQL 索引

PostgreSQL 六大索引的方法小结

作者:Hello.Reader

本文主要介绍了PostgreSQL 六大索引的方法小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

一、概览速览表(先有直觉)

索引类型典型用途支持唯一适配查询优缺点一眼看
B-tree等值、范围、排序、唯一约束=, <, >, BETWEEN, ORDER BY默认首选,通用;维护成本中等
Hash纯等值匹配❌(唯一约束由 B-tree 实现)=仅等值;自 PG10 起 WAL 持久化;使用面窄
GIN倒排类:jsonb、数组、全文、trigram@>, ?, ?&, @@(全文),LIKE/ILIKE(trigram)读快写慢,适合查询多、更新少
GiST距离/范围/空间/相似度、KNN范围、相交、<-> KNN通用“框架”,支持多种数据类型(几何、range、inet…)
SP-GiST前缀/空间分割(trie/k-d/四叉树)前缀、某些 KNN适合强分割数据(前缀搜索、坐标)
BRIN超大表顺序相关列(时间/自增ID)大范围扫描的快速剪枝体积极小,建立/维护极轻;精度低需回检

记忆法:“B 通吃、H 等值、GIN 倒排、GiST 空间、SPG 前缀、BRIN 顺序”

二、B-tree(默认 & 通吃)

特性

常用语法

-- 单列 / 多列
CREATE INDEX idx_user_email ON users(email);
CREATE INDEX idx_orders_user_created ON orders(user_id, created_at DESC);

-- 覆盖索引(减少回表)
CREATE INDEX idx_orders_status_created_inc
ON orders(status, created_at)
INCLUDE (amount);

-- 表达式/部分索引
CREATE INDEX idx_lower_email ON users (lower(email));
CREATE INDEX idx_paid_recent ON orders (created_at)
WHERE status = 'PAID';

实战要点

三、Hash(只做“等值”)

场景:极端等值查找且键宽/比较代价特殊时,可能略小/略快。
限制:不支持唯一约束与范围/排序;面窄,大多数等值场景仍用 B-tree

CREATE INDEX idx_users_hash_email ON users USING hash(email);

备注:自 PG10 起 Hash 索引 WAL 持久化,可崩溃恢复,但优势有限。

四、GIN(倒排:jsonb/数组/全文/trigram)

场景

语法与 opclass

-- jsonb:两种常用 opclass
CREATE INDEX idx_doc_gin ON docs USING gin(data jsonb_ops);       -- 全功能,体积偏大
CREATE INDEX idx_doc_path ON docs USING gin(data jsonb_path_ops);  -- 对 @> 优化更好

-- 数组包含
CREATE INDEX idx_tags_gin ON posts USING gin(tags);

-- 全文
CREATE INDEX idx_posts_fts ON posts USING gin(to_tsvector('simple', title || ' ' || body));

-- trigram 模糊(需扩展)
CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE INDEX idx_user_name_trgm ON users USING gin(name gin_trgm_ops);

调优

-- 批量重放/更新多时:构建或维护参数
CREATE INDEX ... USING gin(...) WITH (fastupdate = on, gin_pending_list_limit = '512MB');

五、GiST(“通用”搜索树:空间/范围/KNN/排斥约束)

场景

示例

-- 范围不重叠的预约(时间区间)
CREATE EXTENSION IF NOT EXISTS btree_gist;

CREATE TABLE booking(
  room_id int,
  during tstzrange,
  EXCLUDE USING gist (room_id WITH =, during WITH &&)  -- 禁止同房间时间相交
);

-- KNN:最近地点
CREATE INDEX idx_poi_gist ON poi USING gist (geom);
SELECT * FROM poi ORDER BY geom <-> ST_SetSRID(ST_MakePoint(121.5,31.2), 4326) LIMIT 20;

要点

六、SP-GiST(空间分割/前缀)

场景

-- 前缀查询
CREATE INDEX idx_phone_prefix ON users USING spgist (phone_number);
SELECT * FROM users WHERE phone_number LIKE '1389%';

特点:对分布不均匀且可递归分割的数据更友好;更新/插入性能通常优于 GiST 的某些场景。

七、BRIN(Block Range Index:大表“顺序相关”神器)

场景

-- 典型配置:pages_per_range 控制摘要粒度(越小越精细)
CREATE INDEX idx_orders_brin_created
  ON orders USING brin (created_at)
  WITH (pages_per_range = 128, autosummarize = on);

要点

八、选型决策 10 条军规

  1. 能用 B-tree 先用 B-tree:等值/范围/排序/唯一都稳。
  2. jsonb/数组/全文/模糊GIN;其中 LIKE '%abc%' 强烈建议 trigram + GIN
  3. 距离/空间/范围相交/KNN → GiST(PostGIS、range、inet 等)。
  4. 前缀或可分割空间结构 → SP-GiST
  5. 超大追加型时间/ID查询 → BRIN
  6. 纯等值且确有收益证据 → Hash;否则 B-tree。
  7. 高频过滤 + 低选择度 → 部分索引WHERE ...)胜过大而全。
  8. 只读回表字段较多 → B-tree INCLUDE 做覆盖扫描。
  9. 表达式要索引同款表达式(如 lower(email));否则无法命中。
  10. 多列顺序要按查询使用频次/选择度从左到右排列;避免“全吃不着”的复合索引。

九、常见坑与对症下药

十、实战模板:一张订单表怎么配索引

CREATE TABLE orders(
  id           bigserial PRIMARY KEY,
  user_id      bigint NOT NULL,
  status       text   NOT NULL,
  created_at   timestamptz NOT NULL DEFAULT now(),
  amount       numeric(12,2) NOT NULL,
  items        jsonb,             -- 订单明细(jsonb)
  tags         text[]             -- 标签
);

-- 1) 用户最近订单(分页/排序)
CREATE INDEX idx_orders_user_created ON orders(user_id, created_at DESC);

-- 2) 状态 + 时间窗口统计(覆盖金额)
CREATE INDEX idx_orders_status_created_inc
  ON orders(status, created_at)
  INCLUDE (amount);

-- 3) jsonb 包含查找(items 内含某 SKU)
CREATE INDEX idx_orders_items_path ON orders USING gin(items jsonb_path_ops);

-- 4) 标签包含任一/全部
CREATE INDEX idx_orders_tags_gin ON orders USING gin(tags);

-- 5) 超大表时间过滤的剪枝
CREATE INDEX idx_orders_brin_created
  ON orders USING brin (created_at) WITH (pages_per_range=128, autosummarize=on);

十一、性能与维护清单

十二、快速对照:你在查什么,就选什么

到此这篇关于PostgreSQL 六大索引的方法小结的文章就介绍到这了,更多相关PostgreSQL 索引内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文