PostgreSQL支持多种索引类型,需根据数据特性(如数据量、是否有序、是否多值)和查询模式(如等值查询、范围查询、全文搜索)选择合适的索引,避免“一刀切”使用B-Tree。
tags @> ARRAY['PostgreSQL'])、JSONB文档的关键字查询(to_tsvector('english', content) @> 'performance')必须使用GIN索引。created_at字段)。索引大小仅几MB,维护成本极低,能快速定位数据块,大幅提升范围查询效率。复合索引(多列索引)不是“列的简单拼接”,列顺序直接决定索引有效性。核心规则是过滤性强的列放前面(过滤性强指该列能显著缩小数据范围,如name的过滤性通常强于age)。
name和age列,若查询常为“按name筛选且age大于30”(WHERE name = 'Alice' AND age > 30),则应创建(name, age)复合索引。该索引能支持:
WHERE name = 'Alice'(左前缀匹配);WHERE name = 'Alice' ORDER BY age(索引自带排序);WHERE age > 30(未匹配左前缀,索引无效)。若查询仅涉及表的部分数据(如“活跃用户”“未删除记录”),可使用部分索引(Partial Index),仅索引符合条件的行,减少索引大小和维护成本。
status = 'active'),可创建部分索引:CREATE INDEX idx_users_active ON users (email) WHERE status = 'active';
该索引仅包含status = 'active'的用户记录,查询时能快速定位,同时减少写操作(INSERT/UPDATE/DELETE)对索引的影响。覆盖索引是指索引包含查询所需的所有列,数据库可直接从索引中获取数据,无需回表查询原表(减少I/O操作)。创建时使用INCLUDE子句添加额外列。
email和name,可创建覆盖索引:CREATE INDEX idx_users_email_name ON users (email) INCLUDE (name);
查询SELECT email, name FROM users WHERE email = 'user@example.com'时,数据库直接从索引中获取email和name,无需访问原表。索引并非“一建永逸”,需定期维护以应对数据增长和写操作带来的碎片问题。
REINDEX命令消除索引碎片(如REINDEX INDEX idx_users_email),或重建整个表(VACUUM FULL users)。建议在低峰期执行,避免影响线上业务。ANALYZE命令更新表的统计信息(如行数、数据分布),帮助查询优化器选择更优的执行计划(如ANALYZE users)。pg_stat_user_indexes视图查看索引的使用频率(如idx_scan表示索引扫描次数),删除长期未使用的索引(如idx_scan = 0的索引),减少写操作开销。即使创建了合适的索引,若查询写法不当,索引仍可能无法使用。需遵循以下原则:
WHERE UPPER(email) = 'USER@EXAMPLE.COM'),会导致索引失效。应改为WHERE email = 'user@example.com',或使用函数索引(CREATE INDEX idx_users_upper_email ON users (UPPER(email)))。EXPLAIN ANALYZE命令查看查询的执行计划(如是否使用了索引、是否有全表扫描),找出性能瓶颈(如Seq Scan表示全表扫描,需检查索引是否合理)。ORDER BY子句与索引的顺序和方向完全一致(如索引为(name ASC),查询为ORDER BY name ASC),数据库可直接使用索引排序,避免额外排序操作。索引能提升查询性能,但过多索引会增加写操作的开销(INSERT/UPDATE/DELETE时需同步维护索引)和磁盘空间占用。需遵循以下原则:
email、订单表的order_date);