当前位置: 首页 > news >正文

什么是覆盖索引?PostgreSQL 是否支持覆盖索引?

这是一个非常好的问题!我们来逐步解释 什么是覆盖索引(Covering Index)、它的作用,以及 PostgreSQL 是否支持覆盖索引


一、什么是覆盖索引(Covering Index)?

覆盖索引 是指:一个索引包含了查询所需的所有列,因此数据库在执行查询时,无需回表(即不需要访问数据行本身),仅通过索引就能完成查询。

换句话说:
✅ 索引“覆盖”了整个查询所需的数据,不需要再去主表中查找其他字段。


二、覆盖索引的作用(优势)

  1. 避免回表(Bookmark Lookup / Random I/O)
    普通索引只存储索引列和主键(或行指针),查到主键后还需要去主表中查找其他字段(回表),这会带来额外的 I/O 开销。
    而覆盖索引直接包含所有需要的字段,避免了回表操作,显著提升性能。

  2. 减少磁盘 I/O 和内存压力
    索引通常比主表小,且可以缓存在内存中,访问更快。

  3. 提升查询速度
    特别是在大表上,覆盖索引能显著加快 SELECT 查询,尤其是高频查询。


三、覆盖索引的示例

假设有一张用户表:

CREATE TABLE users (id SERIAL PRIMARY KEY,name VARCHAR(100),age INT,city VARCHAR(50)
);

你经常执行如下查询:

SELECT name, age FROM users WHERE city = 'Beijing';

如果只对 city 建立索引:

CREATE INDEX idx_city ON users(city);

→ 查询时会先通过索引找到满足 city='Beijing' 的主键 id,然后回表去主表中读取 nameage

但如果建立一个复合索引,包含所有用到的字段:

CREATE INDEX idx_city_name_age ON users(city, name, age);

→ 这个索引就“覆盖”了整个查询所需字段(city 是条件,nameage 是返回值),数据库可以直接从索引中获取所有数据,无需回表 → 这就是覆盖索引


四、PostgreSQL 有覆盖索引吗?

有!PostgreSQL 完全支持覆盖索引,并且提供了多种实现方式。

方式 1:使用 包含列(INCLUDE clause)(推荐)

PostgreSQL 9.4+ 引入了 INCLUDE 子句,可以将非索引列(但需要查询的列)添加到索引中,不参与排序,但包含在索引页中,从而实现覆盖索引。

CREATE INDEX idx_covering ON users(city) INCLUDE (name, age);
  • city 是索引键(用于查找)
  • name, age 是包含列(用于覆盖查询)

✅ 优点:

  • 包含列不参与排序,不影响索引的排序性能
  • 支持数据类型不受限(即使不能作为索引键的类型,如 TEXTJSON

💡 这是 PostgreSQL 实现覆盖索引的最佳实践


方式 2:使用 复合索引(Composite Index)

你也可以直接创建包含所有字段的复合索引:

CREATE INDEX idx_covering_legacy ON users(city, name, age);

→ 也能实现覆盖索引,但缺点是:

  • 所有列都参与排序,可能增加索引大小和维护成本
  • 如果只按 city 查询,但 nameage 的排序无意义,效率不如 INCLUDE

方式 3:使用 表达式索引 + INCLUDE(高级用法)
CREATE INDEX idx_expr_covering ON users((city || '-user')) INCLUDE (name, age);

适用于函数索引场景。


五、MySQL vs PostgreSQL 的覆盖索引对比

特性MySQL(InnoDB)PostgreSQL
是否支持覆盖索引✅(通过复合索引)✅(通过复合索引 + INCLUDE
是否支持 INCLUDE❌ 不支持✅ 支持(9.4+)
覆盖索引实现方式只能用复合索引复合索引 或 INCLUDE(更灵活)
索引大小控制较差(所有列都排序)更好(INCLUDE 列不排序)

✅ 所以:PostgreSQL 不仅支持覆盖索引,而且实现方式更灵活、更高效


六、如何判断是否使用了覆盖索引?

使用 EXPLAINEXPLAIN ANALYZE 查看执行计划:

EXPLAIN SELECT name, age FROM users WHERE city = 'Beijing';

如果执行计划中出现:

  • Index Only Scan → 表示使用了覆盖索引(只需扫描索引,无需回表)
  • Index Scan + Heap Fetch → 表示发生了回表

Index Only Scan 是覆盖索引生效的标志!

注意:要让 Index Only Scan 生效,表还需要做 VACUUM(清理可见性映射),否则 PostgreSQL 无法确定索引行是否对当前事务可见。


七、总结

问题回答
什么是覆盖索引?索引包含了查询所需的所有列,无需回表。
有什么作用?避免回表、减少 I/O、提升查询性能。
PostgreSQL 有覆盖索引吗?✅ 有!支持两种方式:
1. 复合索引(传统方式)
2. INCLUDE 子句(推荐,更灵活)
如何验证?使用 EXPLAIN 查看是否为 Index Only Scan

最佳实践建议(PostgreSQL)

-- 为覆盖查询创建带 INCLUDE 的索引
CREATE INDEX idx_users_city_covering ON users(city) INCLUDE (name, age);

这样既能高效查询,又能控制索引大小和性能。


如果你有具体的查询场景,我可以帮你设计最优的覆盖索引 😊

http://www.dtcms.com/a/406032.html

相关文章:

  • 谨慎地迭代函数所收到的参数 (Effective Python 第31条)
  • ESP32 NTC热敏电阻测温全攻略:从ADC采样到线性插值算法详解
  • 介绍 τ-bench:一个评估语言智能体在真实场景中与人、工具、规则交互能力的新基准
  • 网站模版建设教程效果好网站建设哪家好
  • 20-for循环案例练习
  • 华策影视 AIGC 实战:剧本分镜 1 小时生成,影视创作告别熬夜改稿时代
  • 移动固态硬盘无法被电脑识别怎么办?
  • 突破地域限制:WaveTerminal与cpolar的远程开发协作方案
  • vue2和vue3的watch用法
  • 【Python】文件处理(二)
  • 幸运飞艇网站建设设计网站流程
  • 基于vue的考研信息系统6kv17(程序 + 源码 + 数据库 + 调试部署 + 开发环境配置),配套论文文档字数达万字以上,文末可获取,系统界面展示置于文末
  • 针对单元测试、集成测试、系统测试和验收测试(用户测试)各自的目标和测试内容不同,设计对应的各类测试用例
  • (JDK,Eclipse,Tomcat版本)Java的web配置Part1 (#by 拌面
  • 中企动力算大厂吗周口网站关键词优化
  • 用 Flink DataStream API 搭建流式 ETL从无状态到有状态、从单流到连接流
  • 上海保洁服务网站建设小网站如何做密码找回
  • FreeRTOS内存管理
  • 基于 STM32 的智能洗衣机控制系统设计与实现
  • 【开题答辩全过程】以 IT项目需求发布与管理平台为例,包含答辩的问题和答案
  • 省级旅投集团数据中台架构实战:多租户隔离与主题域建模实践
  • 分布式阳台光伏系统组成及防逆流电表功能详解
  • PostgreSQL 和 MySQL两个数据库的索引的区别
  • 论文流程1
  • 苏州正规制作网站公司去了外包简历就毁了吗
  • 上海网站建设公司哪家好?大淘客怎么自己做网站
  • 解决Markdown笔记图片失效问题:Gitee+PicGo图床搭建全攻略
  • AWS中国云中的ETL之从aurora搬数据到s3(Glue版)
  • 忘记云服务器密码怎么办?阿里云/腾讯云/AWS密码重置官方指南
  • DevOps实战(9) - 使用Arbess+GitPuk+sourcefare+PostIn搭建Java自动化部署