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

关系型数据库sqlserver和pg创建覆盖索引的include写法示例及原理详解

这是一个覆盖索引(Covering Index)的创建语句,让我详细解释它的结构、作用和工作原理:

一、语法结构分解

CREATEINDEXidx_orders_coveringONorders(customer_id,created_date)-- 键列(Key Columns)INCLUDE(amount,status,product_id);-- 包含列(Included Columns)

1.键列(Key Columns)

  • customer_id, created_date:索引的排序和查找键
  • 这些列参与B+树结构
  • 用于WHERE条件、JOIN条件、ORDER BY、GROUP BY

2.包含列(Included Columns)

  • amount, status, product_id非键列,存储在索引叶子节点
  • 不参与B+树排序结构
  • 仅用于"覆盖查询"

二、与传统索引对比

传统复合索引

CREATEINDEXidx_traditionalONorders(customer_id,created_date);-- 索引只包含:customer_id, created_date, order_id(主键)-- 查询其他字段需要"回表"

覆盖索引

CREATEINDEXidx_coveringONorders(customer_id,created_date)INCLUDE(amount,status,product_id);-- 索引包含:customer_id, created_date, amount, status, product_id, order_id-- 无需回表

三、工作原理示例

查询场景

-- 查询1:完全覆盖SELECTcustomer_id,created_date,amount,statusFROMordersWHEREcustomer_id=123ANDcreated_date>='2024-01-01';-- 查询2:部分覆盖SELECTcustomer_id,created_date,amountFROMordersWHEREcustomer_id=123ORDERBYcreated_dateDESCLIMIT10;

执行流程对比

传统索引流程: 1. 使用索引找到符合条件的行位置(索引扫描) 2. 根据主键回表获取完整行数据(回表操作) 3. 从行数据中提取amount, status字段 4. 返回结果 覆盖索引流程: 1. 使用索引找到符合条件的行(索引扫描) 2. 直接从索引叶子节点读取所有需要的字段 3. 返回结果(无需回表!)

四、性能优势

1.消除回表(Bookmark Lookup)

-- 假设orders表有100万行-- 查询返回1000行传统索引:-索引扫描:1000次查找-回表操作:1000次随机IO(每次10ms)-总耗时:约10秒 覆盖索引:-索引扫描:1000次查找-无需回表:所有数据在索引中-总耗时:约0.1秒(快100倍!)

2.减少IO操作

磁盘访问模式: 随机IO(回表):每次10ms 顺序IO(索引扫描):每次0.1ms 覆盖索引将随机IO转为顺序IO

五、INCLUDE子句的优势

与传统方法的对比

-- 方法1:将列加入键列(不推荐)CREATEINDEXidx_badONorders(customer_id,created_date,amount,status,product_id);-- 问题:索引树变得庞大,维护成本高-- 方法2:使用INCLUDE(推荐)CREATEINDEXidx_goodONorders(customer_id,created_date)INCLUDE(amount,status,product_id);-- 优势:包含列不增加索引层级,只增加叶子节点大小

INCLUDE列的特点:

  1. 不参与排序:不影响索引查找效率
  2. 不用于过滤:不能用于WHERE条件
  3. 仅存储值:类似"附表"附加在叶子节点
  4. 更新代价低:修改包含列只更新叶子节点

六、适用场景

1.高频查询优化

-- 报表查询:经常查询固定字段SELECTcustomer_id,created_date,amount,statusFROMordersWHEREcustomer_idIN(1,2,3)ANDcreated_dateBETWEEN'2024-01-01'AND'2024-01-31';-- 创建针对性的覆盖索引CREATEINDEXidx_reportONorders(customer_id,created_date)INCLUDE(amount,status);

2.分页查询优化

-- 分页查询避免大量回表SELECTorder_id,customer_id,created_date,amountFROMordersWHEREcustomer_id=123ORDERBYcreated_dateDESCLIMIT100OFFSET1000;-- 覆盖索引可以完全满足CREATEINDEXidx_pagingONorders(customer_id,created_dateDESC)INCLUDE(amount);

3.聚合查询加速

-- 分组统计SELECTcustomer_id,DATE(created_date),SUM(amount),COUNT(*)FROMordersWHEREcreated_date>='2024-01-01'GROUPBYcustomer_id,DATE(created_date);-- 覆盖索引提供所有需要的数据CREATEINDEXidx_aggONorders(created_date,customer_id)INCLUDE(amount);

七、注意事项和限制

1.索引大小权衡

-- 覆盖索引会更大-- 原始数据:customer_id(8B) + created_date(8B) = 16B-- 覆盖索引:16B + amount(8B) + status(4B) + product_id(8B) = 36B-- 索引大小增加125%,但查询性能提升显著

2.更新代价

-- 更新包含列时UPDATEordersSETamount=200WHEREorder_id=1;-- 需要更新:主表 + 所有包含该列的覆盖索引-- 写操作变慢,读操作变快

3.数据库支持

-- 不同数据库语法不同-- SQL Server/PostgreSQL: 支持INCLUDE语法-- MySQL: 不支持INCLUDE,所有列都是键列-- Oracle: 通过"索引组织表"或"函数索引"实现类似功能-- MySQL的替代方案(没有INCLUDE):CREATEINDEXidx_mysqlONorders(customer_id,created_date,amount,status,product_id);-- 但这不是真正的覆盖索引,所有列都参与排序

八、最佳实践建议

1.选择性包含

-- 只包含高频查询的列CREATEINDEXidx_selectiveONorders(customer_id,created_date)INCLUDE(amount,-- 经常用于SUM/AVGstatus,-- 经常用于筛选-- 不包含:description(大文本字段)-- 不包含:updated_at(很少查询));

2.监控使用情况

-- 检查索引使用SELECT*FROMsys.dm_db_index_usage_statsWHEREobject_id=OBJECT_ID('orders');-- 检查索引大小EXECsp_spaceused'orders';

3.组合策略

-- 针对不同查询创建多个覆盖索引-- 索引1:用于客户查询CREATEINDEXidx_customer_queryONorders(customer_id,created_date)INCLUDE(amount,status);-- 索引2:用于产品分析CREATEINDEXidx_product_analysisONorders(product_id,created_date)INCLUDE(amount,customer_id);-- 索引3:用于状态监控CREATEINDEXidx_status_monitorONorders(status,created_date)INCLUDE(amount,customer_id);
http://www.cnnetsun.cn/news/168251.html

相关文章:

  • 免费在线网盘解析:夸克文件高速下载
  • Git原理与使用
  • 神经网络如何学习:一种概率视角
  • 亲测10款降ai率工具:AI率80%怎么一键降低ai?(2025最新降AIGC避坑指南)
  • PySpark实战 - 2.1 利用Spark SQL实现词频统计
  • PerlinNoise Perlin噪声(PerlinNoise)隐式函数构建模型并渲染
  • Linly-Talker支持模型性能 profiling,精准定位瓶颈
  • Linly-Talker如何处理中英文混读?语音识别适配策略
  • LLM 的思考方式
  • 【虚拟同步机控制建模】三相虚拟同步发电机双环控制(Simulink仿真实现)
  • 万字长文!关于AI绘图,一篇超详细的总结发布
  • 数字人会议主持:Linly-Talker在远程会议中的创新应用
  • 【顶级EI完整复现】【DRCC】考虑N-1准则的分布鲁棒机会约束低碳经济调度(Matlab代码实现)
  • 用Linly-Talker做企业宣传片?品牌传播的AI新路径
  • Electerm(桌面终端模拟软件)
  • Thinkphp和Laravel基于Vue的黄山旅游景区门票预订网站的设计与实现_3h38caai
  • Thinkphp和Laravel基于大数据架构的大学生求职招聘就业岗位推荐系统的设计与实现_67911t4j
  • AI工具实战测评技术
  • 创意AI应用开发大赛技术
  • 全球股市估值与海洋微生物能源技术的关系
  • 基于python的同城宠物照看数据可视化分析系统的设计与实现_34cl0po8--论文
  • 【路径规划】基于RRT快速探索随机树的图像地图路径规划实现3附matlab代码
  • Quartz 工作模式,是“堵塞排队”还是“并发狂奔”?
  • 【FFNN负荷预测】基于人工神经网络的空压机负荷预测(Matlab代码实现)
  • 【C2000系列DSP的反向灌电流】为什么热插拔的时候I2C总线电平会被拉低?
  • Gemini Inc靶场练习(包含suid提权,文件包含漏洞,ssh免密登录)
  • 软件解耦与扩展:插件式开发方式(基于 C++ 与 C# 的实现)
  • 免费降AI率的工具红黑榜:认准这2个免费降AI率工具,亲测有效!
  • 霍华德·马克斯的市场周期定位技巧
  • 1500字免费降AIGC率的额度,2026年毕业论文查重必备!