dbaplus社群 前天 23:37
千万级数据的订单表,给订单状态加索引有用吗?在线等!
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文探讨了在千万级别数据量的表中,为status字段添加索引是否有效的问题。文章从索引的简单执行流程入手,分析了极端场景下索引的选择,以及order_status字段的区分度和选择性对索引效果的影响。同时,结合查询数据量的大小、与其他字段的联合使用、分区表等因素,全面评估了索引的有效性。最后,建议使用EXPLAIN查看查询计划,以判断索引是否真正发挥作用,从而为数据库优化提供参考。

🔑 加索引后,查询会先从索引树查找,找到主键ID后再回表查询完整记录,但MySQL优化器会根据情况选择全表扫描或索引查询。

📊 索引效果与order_status字段的区分度和选择性密切相关。区分度越高,索引效果越好;反之,如果字段值重复率高,索引可能不会显著提升查询效率。

🔍 查询数据量大时,即使有索引,数据库也可能倾向于全表扫描。此时可考虑使用覆盖索引或分页优化。深分页优化可以使用标签记录法。

🧩 结合其他字段查询时,加联合索引效果更明显。例如,查询某个客户的已完成订单,可以加idx_client_no_order_status联合索引。

📈 对于数据量大的订单表,可以考虑使用分区表,根据order_status或其他高选择性字段进行分区,提高查询效率。

捡田螺的小男孩 2025-04-27 07:16 广东

被问的时候,大脑一片空白……


前言


有位读者去快手面试,问了这道题:一个表拥有千万级别数据量,给status字段加索引,是否有效?


这道面试题,还是可以从几个维度结合去回答的,我来跟大家聊聊我的看法~~


    加了索引的简单执行流程

    极端场景,走索引or全表扫描

    status区分度与选择行

    查询的数据量的影响

    结合不同场景的其他字段

    分区表

    EXPLAIN 查询计划


一、加了索引的简单执行流程


我觉得,在回答这个问题,可以跟面试官说说,普通索引加入后的简单执行流程.


假设有一张订单表order_info,然后订单状态字段order_status,有个普通索引idx_order_status,它是B+树索引.


我们现在简单点查询,就是查询已完成FINISHED的历史订单:


    select * from order_info where order_status = 'FINISHED'


    我们来说一下这个执行流程:


      从idx_order_status这棵 B+ 树的根节点开始查找。因为B+ 树是有序的,使用二分查找的方法逐层向下查找,直到找到包含FINISHED的叶子节点。


      找到FINISHED的起始位置后,数据库会扫描所有包含FINISHED的叶子节点。因为叶子节点存储了主键ID的值.它会遍历索引的叶子节点,以收集所有匹配FINISHED的记录的主键 ID。


      使用从idx_order_status索引中获取的主键 ID,数据库会回到ID主键索引树,找到对应的行记录(这个过程叫做回表)。


    二、极端场景,走索引or全表扫描


    我先给大家讲解一个极端情况: 假设订单表里面,全部记录的订单,它的状态都是FINISHED.


    那我们的这个查询SQL,它还会先找idx_order_status 索引树,找到FINISHED的叶子节点,然后找到主键id后,再回表,找到对应的记录吗?


    那肯定不会呀,我们都知道MySQL有优化器的,它发现这一波操作下来(又B+索引树搜索,又回表,多次IO),还没全表扫描快,那就肯定不走索引啦,而是选择全表扫描啦.



    这个极端情况,大家应该能理解吧? 那我们再往下一步,假设一千万数据的表,有那么的几条数据,它的订单状是已下单.其他状态都是已完成(FINISHED),那么你觉得会走索引嘛?


    那也不会走索引,因为mysql执行查询的时候,假设走索引,还是那一波操作(又B+索引树搜索,又回表,多次IO), 只有几条其他状态的记录,最后时间肯定也是没有直接全表扫描快的.因此还是会全表扫描.


    三、order_status 区分度与选择性


    对于这道面试题,粉丝们讨论过,我摘抄来一些讨论点下来,给大家看看:


    如果orderStatus字段的值分布很广,那么索引会更有效。如果大多数行都有相同的状态值,索引效果可能不佳

    数据倾斜严重:如果status字段的值分布极不均匀,大部分数据集中在少数几个状态上,索引的选择性就会降低,查询效率提升有限


    首先增加索引肯定会需要额外的空间去储存,另外会影响增删改的性能 其次离散性低代表通过索引筛选出的数据量较多,例如status三种状态,1/3的数据和整体数据提升效果较小 然后通过二级索引查询数据,是先通过二级索引查询id,然后在通过id去聚簇索引查找数据,多增加一次io消耗


    这些观点,其实都跟区分度和选择性有关.比如,订单表有好多种状态,每种状态的数据量都比较均衡,也就是说订单各种状态区分度很好. 再换种专业说法吧,选择性


    选择性(Cardinality) 是指列中不同值的数量与总记录数的比例。简单来说,选择性越高(即字段的不同值越多、重复率越低),索引的效果就越好。


      如果 status 字段的值非常少且重复率高(例如只有 "下单"、"已支付"、"已取消" 这几种状态),那么普通索引可能不会显著提升查询,因为数据库可能会选择进行全表扫描。这种情况下,索引的选择性太低,查询时即便走索引,命中的行数也会很多,反而可能导致查询性能变差。


    那我们怎么判断,这个选择性呢? 有个方法


    判断方法:可以通过 MySQL 的 SHOW INDEX 命令查看索引的 Cardinality 值,它表示索引的选择性。值越大,索引越有效。sql SHOW INDEX FROM order_info WHERE Key_name = 'idx_order_status'; 如果 Cardinality 很低,说明创建的普通索引对性能提升不大。


    四、查询的数据量的影响


    如果查询返回的数据量很大,比如查询状态为 "已完成" 的所有订单,即使有索引,数据库可能也会倾向于全表扫描,因为回表操作(即通过索引找到记录后再根据主键去查找完整行数据)可能比全表扫描还要慢。


    这时候,我们可以做一些优化,比如,使用覆盖索引


    即将查询的字段都包含在索引中,避免回表。例如,如果你的查询只需要 order_status 和 order_id,那么可以为 order_status 和 order_id 创建联合索引,这样索引中就可以直接返回结果,而不需要回表查询数据。


    有些时候,比如你查询已完成的订单,如果返回的数据量特别多,一般要求用分页的,这时候,基于分页,可以针对一些做深分页优化,比如使用标签记录法.



    五、结合不同场景的其他字段


    单纯查已完成订单的话,业务场景是比较少的. 一般结合其他场景来一起使用.


    如果是结合其他场景,那加联合索引,效果就会比较明显啦.


      比如查询某个客户的已完成订单,就是说结合客户号来一起查询,这时候加联合索引 idx_client_no_order_status查询效果就很明显.


      又或者查询最近三个月的已完成订单,就是说结合订单创建时间来查询.加联合索引idx_create_time_order_status查询效果也很不错


    六、分区表


    如果有些时候,你的查询只是根据订单条件来查,不结合其他场景的字段. 那还是可以做一些优化,比如分区表.


    如果订单表的数据量很大(如上千万级别),考虑使用分区表,可以基于 order_status 字段或其他高选择性的字段进行分区。分区表可以将数据按指定规则分布到多个物理存储区域中,查询时只需要扫描部分分区,提高查询效率。


    七、EXPLAIN 查询计划


    我们写完查询SQL的时候,经常建议用EXPLAIN 查看一下查询计划.通过 EXPLAIN 查看查询计划,判断是否使用了索引,以及该索引是否在查询中实际被用到。


    例如:


      EXPLAINSELECT * FROM order_info WHERE order_status = 'FINISHED';


      看看是否返回了 index 或 ref 这样的结果。如果查询结果中没有显示索引使用(如 type 为 ALL,表示全表扫描),说明当前的索引并没有起作用。


      作者丨捡田螺的小男孩
      来源丨公众号:捡田螺的小男孩(ID:gh_3d11c9893ca0)
      dbaplus社群欢迎广大技术人员投稿,投稿邮箱:editor@dbaplus.cn


      数据库相关活动推荐


      汇集2025年讨论度最高的数据库议题,XCOPS智能运维管理人年会将于5月16日在广州举办。大会精选金融核心系统数据库切换、多模态数据库设计、存算分离架构搭建,以及云原生数据库、数仓及数据湖的创新实践等干货案例,就等你扫码一起来探讨↓


      阅读原文

      跳转微信打开

      Fish AI Reader

      Fish AI Reader

      AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

      FishAI

      FishAI

      鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

      联系邮箱 441953276@qq.com

      相关标签

      数据库索引 性能优化 MySQL 大数据 EXPLAIN
      相关文章