news 2026/9/13 2:38:42

MySQL 5.7覆盖索引的实现方式、替代方案和限制

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MySQL 5.7覆盖索引的实现方式、替代方案和限制

由于MySQL 5.7 不支持INCLUDE语法!本文我详细解释MySQL 5.7覆盖索引的实现方式、替代方案和限制:

一、MySQL的覆盖索引实现方式

MySQL 5.7的实际语法

-- MySQL 5.7 不支持INCLUDE语法-- 以下语句会报错:CREATEINDEXidx_orders_coveringONorders(customer_id,created_date)INCLUDE(amount,status,product_id);-- ❌ 语法错误!-- MySQL的正确写法:CREATEINDEXidx_orders_coveringONorders(customer_id,created_date,amount,status,product_id);-- ✅

工作原理差异

-- SQL Server/PostgreSQL:键列和包含列分离CREATEINDEXidx_separateONtable(key1,key2)INCLUDE(col3,col4);-- 索引结构:key1, key2 | col3, col4 (附加存储)-- MySQL:所有列都是键列CREATEINDEXidx_all_keysONtable(key1,key2,col3,col4);-- 索引结构:key1, key2, col3, col4 (全部参与排序)

二、MySQL 5.7的替代方案

方案1:创建复合索引(最常用)

-- 将所有需要的列都放在索引定义中CREATEINDEXidx_covering_mysqlONorders(customer_id,created_date,amount,status,product_id);-- 查询验证EXPLAINSELECTcustomer_id,created_date,amount,statusFROMordersWHEREcustomer_id=123ANDcreated_date>='2024-01-01';-- 如果Extra显示"Using index",说明使用了覆盖索引

方案2:使用索引扩展(MySQL 5.6+)

-- MySQL会自动将主键附加到二级索引末尾-- 假设主键是order_idCREATEINDEXidx_partialONorders(customer_id,created_date);-- 实际索引包含:customer_id, created_date, order_id-- 可以利用这一点SELECTcustomer_id,created_date,order_idFROMordersWHEREcustomer_id=123;-- 这个查询可以使用覆盖索引

方案3:使用生成列(MySQL 5.7+)

-- 通过生成列创建函数索引ALTERTABLEordersADDCOLUMNstatus_codeTINYINTAS(CASEstatusWHEN'pending'THEN1WHEN'shipped'THEN2WHEN'delivered'THEN3ELSE0END)STORED;-- 创建包含生成列的索引CREATEINDEXidx_with_storedONorders(customer_id,created_date,status_code);

三、MySQL覆盖索引的局限性

1.索引大小问题

-- MySQL中所有索引列都参与B+树排序-- 如果包含大字段,索引会非常庞大CREATEINDEXidx_bigONorders(customer_id,created_date,product_nameVARCHAR(200),-- 大字段会使索引很大descriptionTEXT(500)-- 更糟糕!);-- ❌ 不推荐,可能比表数据还大

2.前缀索引限制

-- 对于文本字段,可以使用前缀索引CREATEINDEXidx_text_prefixONorders(customer_id,created_date,product_name(50)-- 只索引前50个字符);-- 但可能无法完全覆盖查询SELECTcustomer_id,created_date,product_nameFROMordersWHEREcustomer_id=123;-- 如果product_name长度超过50,需要回表

3.最左前缀原则限制

-- 索引:customer_id, created_date, amount, status-- 有效查询:SELECT*FROMordersWHEREcustomer_id=123;-- ✅ 使用索引SELECT*FROMordersWHEREcustomer_id=123ANDcreated_date>'2024-01-01';-- ✅-- 无效查询:SELECT*FROMordersWHEREcreated_date>'2024-01-01';-- ❌ 不使用索引SELECT*FROMordersWHEREamount>100;-- ❌ 不使用索引

四、MySQL 5.7的优化技巧

技巧1:选择合适的列顺序

-- 按选择性和查询频率排序CREATEINDEXidx_optimizedONorders(customer_id,-- 高选择性,经常用于WHEREcreated_date,-- 范围查询,放在第二status,-- 低选择性,很少单独查询amount-- 仅用于SELECT列表);

技巧2:使用索引合并

-- 如果无法创建大型复合索引CREATEINDEXidx_customer_dateONorders(customer_id,created_date);CREATEINDEXidx_statusONorders(status);-- 查询时MySQL可能使用索引合并EXPLAINSELECTcustomer_id,created_date,amountFROMordersWHEREcustomer_id=123ANDstatus='shipped';-- 可能使用:idx_customer_date AND idx_status

技巧3:分析索引使用情况

-- 查看索引统计SELECTTABLE_NAME,INDEX_NAME,SEQ_IN_INDEX,COLUMN_NAME,CARDINALITYFROMINFORMATION_SCHEMA.STATISTICSWHERETABLE_SCHEMA='your_database'ANDTABLE_NAME='orders'ORDERBYINDEX_NAME,SEQ_IN_INDEX;-- 查看索引大小SELECTTABLE_NAME,INDEX_NAME,ROUND(INDEX_LENGTH/1024/1024,2)AS'Size(MB)'FROMINFORMATION_SCHEMA.TABLESWHERETABLE_SCHEMA='your_database'ANDTABLE_NAME='orders';

五、MySQL 8.0的改进

降序索引(MySQL 8.0+)

-- MySQL 5.7不支持降序索引,8.0支持CREATEINDEXidx_descONorders(customer_id,created_dateDESC);-- 对于ORDER BY ... DESC查询更高效

函数索引(MySQL 8.0+)

-- 直接在索引中使用函数CREATEINDEXidx_funcONorders((UPPER(customer_name)));

六、实际应用示例

场景:订单查询优化

-- 查询模式1:按客户和时间查询SELECTorder_id,customer_id,created_date,amount,statusFROMordersWHEREcustomer_id=123ANDcreated_dateBETWEEN'2024-01-01'AND'2024-01-31';-- 查询模式2:按状态和时间查询SELECTorder_id,customer_id,created_date,amountFROMordersWHEREstatus='shipped'ANDcreated_date>='2024-01-01';-- MySQL 5.7解决方案:创建两个索引CREATEINDEXidx_customer_date_coveringONorders(customer_id,created_date,amount,status);-- 注意:order_id会自动包含(主键)CREATEINDEXidx_status_date_coveringONorders(status,created_date,customer_id,amount);

七、最佳实践建议

1.避免过度索引

-- 不要为每个查询创建覆盖索引-- 评估查询频率和性能收益-- 一般原则:一个表的索引数量不超过5-7个

2.监控和维护

-- 定期分析索引使用SELECT*FROMsys.schema_unused_indexes;-- MySQL 8.0+-- 使用Performance Schema监控SELECT*FROMperformance_schema.table_io_waits_summary_by_index_usage;

3.测试验证

-- 创建索引前测试EXPLAINSELECT...-- 查看执行计划-- 创建索引后验证ANALYZETABLEorders;-- 更新统计信息EXPLAINSELECT...-- 确认索引使用
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 5:18:22

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

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

作者头像 李华
网站建设 2026/9/12 4:39:31

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

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

作者头像 李华
网站建设 2026/9/10 16:15:18

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

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

作者头像 李华
网站建设 2026/9/12 9:46:22

2004-Image thresholding using Tsallis entropy

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

作者头像 李华
网站建设 2026/9/13 4:12:07

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

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

作者头像 李华