• 一次由 select * 走了索引而引发的思考



    问题描述

    一次偶然,发现 select * 居然走了索引,看来这是个知识漏洞,想着稍稍研究下。

    建表语句如下:

    CREATE TABLE `realtime_event_rw` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      `device_id` int(10) unsigned NOT NULL COMMENT '接入设备id',
      `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '事件发生时间',
      `processing_state` tinyint(1) unsigned DEFAULT '2' COMMENT '事件状态:0:已消除,1:已确认,2:未处理,3:暂缓处理 , 4:自动确认,5:漏报',
      `processing_time` timestamp NULL DEFAULT NULL COMMENT '事件处理的时间;已设置为自动获取当前时间戳',
      `video_address` varchar(500) DEFAULT NULL COMMENT '事件视频地址',
      `img_address` varchar(500) DEFAULT NULL COMMENT '图片地址',
      `analysis_img_address` varchar(500) DEFAULT NULL COMMENT '包含检测跟踪信息的图片地址',
      `finger_print` json DEFAULT NULL COMMENT '{"queue_length":0,"free_or_busy":0}',
      `alarm_type` varchar(20) DEFAULT '0' COMMENT '告警方式;格式:0|1|2;0:不告警,1:客户端告警,2:声音告警,3:声光告警,4:手环告警;参见config_dictionary中item_id=115的子节点',
      `alarm_level` smallint(1) unsigned DEFAULT '0' COMMENT '告警级别;0:未知 1:紧急 2:重要 3:一般 4:非关注;\\r\\n\\r\\n参见config_dictionary中item_id=103的子节点',
      `operator_id` int(10) DEFAULT NULL COMMENT '操作人员id',
      `check_user_id` int(10) DEFAULT NULL COMMENT '检查人员id',
      `remark` varchar(500) DEFAULT '' COMMENT '备注信息',
      `ori_img_address` varchar(500) DEFAULT NULL COMMENT '原始图片',
      `warning_num` int(10) DEFAULT '0' COMMENT '危险物品数量',
      `mec_id` varchar(100) NOT NULL COMMENT '盒子告警id',
      `mec_name` varchar(255) DEFAULT NULL COMMENT '盒子名字',
      `mec_event_id` int(10) unsigned NOT NULL COMMENT '盒子事件id',
      `review_state` int(5) DEFAULT '0' COMMENT '数据状态 0上报 1已检测无异常 2已检测有异常',
      `review_warning_num` int(10) DEFAULT NULL COMMENT '复核危险物品数量',
      `receive_time` datetime DEFAULT NULL COMMENT '数据接收时间',
      `review_time` datetime DEFAULT NULL COMMENT '二次处理完成时间',
      PRIMARY KEY (`id`) USING BTREE,
      KEY `idx_rt_event_camera_id` (`device_id`) USING BTREE,
      KEY `idx_rt_event_processing_state` (`processing_state`) USING BTREE,
      KEY `idx_rt_event_time` (`time`) USING BTREE
    ) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8mb4 COMMENT='二次识别告警明细表';
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    查询语句如下:

    select
    	*
    from
    	realtime_event_rw
    where
    	time between '2022-08-27 17:30:22' and '2022-08-27 19:30:22'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    查询结果

    在这里插入图片描述

    问题分析

    用 explain 查看语句执行情况:

    在这里插入图片描述

    没想到这里使用了索引(一直误以为使用 select * 就会导致索引失效😂)。

    select * 走不走索引,关键取决于 where 后面是否包括有效的索引字段,和 select * 没有关系,select * 最大的影响就是额外的 IO 开销。

    开始怀疑是因为结果集为空而导致的,于是修改查询条件去查询表中所有数据。

    在这里插入图片描述

    这种情况 select * 已经不走索引了,所以怀疑可能和结果集数量或者大小有关。因此,尝试只查询两个字段,判断是否和大小结果集有关。

    只查询一个字段(主键 id 除外)

    在这里插入图片描述

    由上图可知,select * 走不走索引与结果集大小无关,而应该和结果集数量有关。

    之后,查阅资料后得知:

    查询到的结果集数量,如果超过了总行数的 25%,优化器就会认为没有必要走索引了(主键索引除外,仍然会走索引)。

    验证结论

    场景一:总记录数为 17,结果集记录数为 4,略低于 25%

    在这里插入图片描述

    场景二:总记录数为 17,结果集记录数为 5,略高于 25%

    在这里插入图片描述

    经简单验证后,确定结论正确。

  • 相关阅读:
    0106极限存在准则两个重要的极限-函数与极限
    【TCP】三次握手 与 四次挥手 详解
    不可思议,红警居然开源了!
    【第三篇】- 深入学习Git 工作流程
    Scrapy入门
    Verilog:【6】PWM调制器(pwm_modulator.sv)
    C++进阶篇2---多态
    Win10 桌面图标出现空文件夹的删除及桌面图标排列问题
    重写与重载and抽象类与接口!!!!
    Calculation View里的Keep Flag 和 Transparent Filter
  • 原文地址:https://blog.csdn.net/TQ20160412/article/details/126558022