首页 > 数据库 >MYSQL因IN的范围太大导致索引失效问题

MYSQL因IN的范围太大导致索引失效问题

时间:2023-02-08 00:33:05浏览次数:52  
标签:阈值 扫描 id 索引 全表 MYSQL 失效 主键

背景

最近发现有个用于统计的门店串码激活数量的SQL特别慢,将其摘出来大致如下

SELECT a.sku_id as skuId,a.store_id as storeId,
count(*) as saleQty
FROM all_imei_info a
where
    a.activated_time >= 1675530000000
    and a.activated_time <= 1675616399999
    and a.store_id in ('1','2',....'23401')
group by a.sku_id,a.store_id

这张表中的activated_time和store_id均有索引,但是先线上explain时却是走的全表扫描。

当初写这个SQL的开发人员,本意是想按天统计当下所有门店的一个销量情况,但是错就错在,他先在外层将所有区域查出来,再放到统计SQL的IN语句里面,这样就会导致索引失效。

 在整个系统中有2w多个门店,而这个定时任务就是要每天把所有的门店都跑一下,所以说sotre_id in 就是把所有的storeId都放进来了。而mysql有个阈值,决定了阈值之下使用索引查询,而超过阈值,网上说当in的条件命中的数量超过30%时,索引失效,走全表扫描。

 后面放弃使用in的方式,直接改为连表查询,即可正常使用索引,速度快的飞起。
SELECT a.sku_id as skuId,a.store_id as storeId,
count(*) as saleQty
FROM all_imei_info a
where
    a.activated_time >= 1675530000000
    and a.activated_time <= 1675616399999
    and a.store_id in (select store_id from store_table where is_del = 0)
group by a.sku_id,a.store_id

MySQL中IN数据范围不同导致索引使用不同

EXPLAIN:explain 命令获取 select 语句的执行计划,通过 explain我们可以知道以下信息:表的读取顺序,数据读取操作的类型,哪些索引可以使用,哪些索引实际使用了,表之间的引用,每张表有多少行被优化器查询等信息

其中explian结果中的type字段很明显提现是否用到索引。

常见的扫描方式:

 

system:系统表,少量数据,往往不需要进行磁盘 IO
const:常量连接(通常情况下,如果将一个主键放置到where后面作为条件查询,mysql优化器就能把这次查询优化转化为一个常量。)
eq_ref:主键索引 (primary key) 或者非空唯一索引 (unique not null) 等值扫描
ref:非主键非唯一索引等值扫描(查找条件列使用了索引而且不为主键和unique。)
range:范围扫描(有范围的索引扫描,相对于index的全表扫描,他有范围限制,因此要优于index)
index:索引树扫描(另一种形式的全表扫描,只不过他的扫描方式是按照索引的顺序)
ALL:全表扫描 (full table scan)
其中:MySQL索引扫描方式由快到慢依次为:

system > const > eq_ref > ref > range > index > ALL

下面展示查询sql及结果

当IN只有一个主键时:

结果: type:const,走的主键索引。

当IN多个主键时:结果:type:range,此时仍然走了索引,但是效率降低了。

当IN范围继续扩大时:

结果:type:all,没有走索引了,而是全表扫描。

结论:IN肯定会走索引,但是当IN的取值范围较大时会导致索引失效,走全表扫描。

原因是:mysql有个阈值,决定了阈值之下使用索引查询,而超过阈值则退化,优化器选择索引下潜。

MySQL优化器决定使用某个索引执行查询的仅仅是因为:使用该索引时的成本足够低。

 

相关文章:

https://blog.csdn.net/dmedaa/article/details/124245351

 

本篇文章如有帮助到您,请给「翎野君」点个赞,感谢您的支持。 

首发链接:https://www.cnblogs.com/lingyejun/p/17100242.html

标签:阈值,扫描,id,索引,全表,MYSQL,失效,主键
From: https://www.cnblogs.com/lingyejun/p/17100242.html

相关文章

  • 72、商城业务---Mysql报错---Group By使用注意事项
    原sql语句:SELECT info.sku_id, ssav.attr_id, ssav.attr_name, ssav.attr_valueFROM`pms_sku_info`infoLEFTJOIN`pms_sku_sale_attr_value`ssavONssav.sku......
  • centos7安装mysql数据库
    一、centos7(linux)安装mysql7.5.0前要先删除本机安装的mariadb(一)检查当前系统是否自带mysql相关程序文件1.检查已经安装的mariadb列表(rpm命令是RPM软件包的管理工具)......
  • 用Navicat把MySql数据库的表按照表名、表名注释、字段名、字段类型、字段注释、约束类
    --用Navicat把MySql数据库的表按照表名、表名注释、字段名、字段类型、字段注释、约束类型的排列顺序导出selectt.table_name表名,t.table_comment表名注释,c.colu......
  • 【MAC系统】mysql相关命令行
    Linux下的MySQL使用非常方便,Mac相对来讲并不是说不方便,可能更多的是不熟悉,毕竟Mac主要是通过dmg安装的.一般情况我们可能会在设置里面去启动或停止MySQL,但有些时......
  • 索引的分类及优化回表查询的方案
    索引可以按照以下几个角度进行分类:从数据结构的角度分类B+tree索引Hash索引Full-texts索引从物理存储的角度分类聚簇索引二级索引【辅助索引】从索引字段......
  • 【Mysql】CentOS7 安装mysql8.0(RPM方式)
    前言:最近在某个项目上,需要在linux服务器上安装数据库,最初时通过YUM的方式安装数据库,结果发过字符集异常。经调查发现,我开发电脑上使用的Mysql版本时8.0.15,但是通过YUM安装......
  • 软件测试|MySQL安装最全教程
    MySQL的下载与安装、基本使用、系统服务制作MySQL简介MySQL是一种关系型数据库管理系统,关系数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速......
  • 统一观测丨如何使用 Prometheus 监控 MySQL
    作者:在峰MySQL作为最流行的关系型数据库管理系统之一,非常多系统的后端存储都有着MySQL的身影,可谓是广泛应用于各行各业。与此同时,数据库作为应用服务的核心组件,直接影响着......
  • 统一观测丨如何使用 Prometheus 监控 MySQL
    作者:在峰MySQL作为最流行的关系型数据库管理系统之一,非常多系统的后端存储都有着MySQL的身影,可谓是广泛应用于各行各业。与此同时,数据库作为应用服务的核心组件,直接影响......
  • B-Tree(B+Tree)与Hash索引的限制
    index(name,age,sex)B-Tree(B+Tree)限制查询条件不包括最左列,无法使用索引whereage=5andsex=1无法使用索引跳过了索引中的列,则无法完全使用索引w......