news 2026/8/3 7:21:10

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
关系型数据库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);
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/2 2:07:35

从文本到数字人视频:Linly-Talker全流程演示

从文本到数字人视频:Linly-Talker全流程解析 在虚拟主播24小时不间断带货、AI客服秒回千条咨询的今天,一个更高效、更低门槛的数字人生成方案正悄然改变内容生产的底层逻辑。你是否想过,只需一张照片和一段文字,就能让静态肖像“活…

作者头像 李华
网站建设 2026/8/2 15:20:41

掌握AI原生应用领域函数调用的核心要点

AI原生应用函数调用:从原理到实战的7个核心密码 关键词 AI原生应用、函数调用、工具集成、上下文管理、prompt工程、安全性、性能优化 摘要 当我们谈论「AI原生应用」时,本质上是在说「让AI成为应用的大脑,自主指挥工具完成任务」。而函数调用,就是AI大脑与外部工具之间…

作者头像 李华
网站建设 2026/8/2 3:51:44

Linly-Talker对显卡配置的要求及性价比推荐

Linly-Talker 显卡配置深度解析与性价比选型指南 在虚拟主播、数字员工和智能导播系统日益普及的今天,一个能“听懂”用户提问、“说出”自然回复并“张嘴同步”的数字人,早已不再是科幻电影里的设定。开源项目 Linly-Talker 正是这一趋势下的技术先锋—…

作者头像 李华
网站建设 2026/8/1 20:37:00

2004-Image thresholding using Tsallis entropy

注:博主并非旨在对针对文章中提及论文的实验设计、数据及结果进行逐一还原,而是针对其核心方法论或关键创新点,通过自行设计的实验流程进行验证与探索。若是完整的论文复现,会进行提前说明。 1 论文简介 《Image thresholding usi…

作者头像 李华
网站建设 2026/8/2 4:37:32

免费在线文件解析 - 夸克网盘解析

今天教大家一招能解决夸克网盘限制的在线工具。这个工具也是完全免费使用的。下面让大家看看我用这个工具的下载速度咋样。地址获取:放在这里了,可以直接获取 这个速度还是不错的把。对于平常不怎么下载的用户还是很友好的。下面开始今天的教学 输入我给…

作者头像 李华