2. PostgreSQL 索引基础回顾:B-Tree、Hash、GiST、GIN 索引原理与适用场景

索引是数据库性能优化的基石。PostgreSQL 提供了丰富的索引类型,每种索引都有其独特的数据结构和适用场景。理解这些索引的原理,是后续学习函数索引和缓存优化的前提。本章将系统回顾四种最核心的索引类型:B-Tree、Hash、GiST 和 GIN。

2.1 B-Tree 索引:通用型索引的标杆

B-Tree(平衡树)是 PostgreSQL 默认且最通用的索引类型。它适用于等值查询、范围查询、排序和部分匹配(LIKE 'prefix%')。B-Tree 索引将数据组织成一种自平衡的树形结构,所有叶子节点位于同一深度,保证了查询的时间复杂度为 O(log n)。

核心特性:支持 <、<=、=、>=、> 以及 BETWEEN 操作符;支持 ORDER BY 的排序优化;支持 NULLS FIRST/LAST 控制。
适用场景:主键索引、唯一约束、外键列、经常需要排序或范围过滤的字段(如订单创建时间、用户年龄)。
B-Tree 索引结构示意图 根节点 [50, 120] 内部节点 [10, 30] 内部节点 [80, 150] 叶子 [1, 5, 8] 叶子 [12, 25] 叶子 [55, 70] 叶子 [85, 100] 叶子 [130, 200] 叶子节点之间通过双向链表连接,支持高效的范围扫描(如 WHERE age BETWEEN 20 AND 40)

2.2 Hash 索引:等值查询的利器

Hash 索引基于哈希表实现,仅支持等值比较(=)操作。它将索引键通过哈希函数映射到一个固定长度的哈希值,然后直接定位到对应的数据桶。Hash 索引在等值查询上通常比 B-Tree 更快,但不支持范围查询和排序。

注意事项:PostgreSQL 10 之前的 Hash 索引在崩溃恢复后可能不稳定,建议使用 PostgreSQL 10 及以上版本。Hash 索引不适用于 ORDER BY 或 LIKE 操作。
特性 B-Tree 索引 Hash 索引
支持操作符 =, <, >, BETWEEN, LIKE 仅 =
排序优化 支持 ORDER BY 不支持
范围查询 高效 不支持
适用场景 通用型,OLTP 和 OLAP 高并发等值查询(如用户 ID 精确查找)

2.3 GiST 索引:空间与范围数据的通用框架

GiST(Generalized Search Tree)是一种平衡树结构的通用索引框架,它不局限于单一数据类型。GiST 索引支持自定义的“距离”和“包含”操作,特别适合处理空间数据(几何类型、地理坐标)、范围类型(如 int4range)以及全文搜索的某些场景。

核心优势:支持 <<(左)、&&(重叠)、@>(包含)等空间操作符;支持 ORDER BY 与距离排序(如 ORDER BY geom <-> point(10,20))。

GiST 索引的典型应用包括:

  • 地理信息系统(GIS):使用 PostGIS 扩展时,对几何列创建 GiST 索引以加速空间查询。
  • 范围类型:对 tsrange、daterange 等范围列进行重叠或包含查询。
  • 多维数据:使用 cube 或 seg 扩展时的相似性搜索。

2.4 GIN 索引:全文搜索与数组的王者

GIN(Generalized Inverted Index)是一种倒排索引,专为处理复合值(如数组、JSONB、全文搜索的 tsvector)设计。它将每个元素(如单词、数组元素)映射到包含该元素的文档列表,从而支持高效的包含和重叠查询。

适用场景:全文搜索(tsvector 列)、数组列(int[]、text[])、JSONB 列(@>、? 操作符)。
GIN 倒排索引结构示意图 词条(Term) "PostgreSQL" "索引" "优化" "缓存" 文档 ID 列表 Doc1, Doc3, Doc5 Doc2, Doc4 Doc1, Doc5 Doc3, Doc4 每个词条指向包含该词条的所有文档 ID,支持快速查找包含特定元素的记录

2.5 索引类型对比与选择指南

在实际开发中,选择合适的索引类型对查询性能至关重要。下表总结了四种索引的核心差异和推荐场景:

索引类型 数据结构 核心操作符 典型场景 注意事项
B-Tree 平衡树 =, <, >, BETWEEN, LIKE 主键、外键、排序、范围查询 默认索引,通用性最强
Hash 哈希表 = 高并发等值查询 不支持范围查询,PostgreSQL 10+ 稳定
GiST 平衡树(通用框架) &&, @>, <-> 空间数据、范围类型、距离排序 可扩展性强,支持自定义操作符
GIN 倒排索引 @>, ?, @@ 全文搜索、数组、JSONB 更新较慢,适合读多写少场景
选择口诀:等值排序用 B-Tree,纯等值用 Hash,空间范围用 GiST,复合元素用 GIN。

2.6 索引创建示例

以下代码展示了在 PostgreSQL 中创建上述四种索引的典型语法:

-- B-Tree 索引(默认)
CREATE INDEX idx_users_created_at ON users (created_at);

-- Hash 索引
CREATE INDEX idx_users_email ON users USING hash (email);

-- GiST 索引(需安装 btree_gist 扩展以支持范围类型)
CREATE EXTENSION IF NOT EXISTS btree_gist;
CREATE INDEX idx_reservations_duration ON reservations USING gist (duration);

-- GIN 索引(全文搜索)
CREATE INDEX idx_articles_tsv ON articles USING gin (tsv);

-- GIN 索引(数组列)
CREATE INDEX idx_tags_array ON posts USING gin (tags);
性能提示:对于 GIN 索引,如果更新频繁,可以设置 gin_pending_list_limit 参数来平衡插入速度和查询性能。对于 B-Tree 索引,定期执行 REINDEX 可以消除索引膨胀。