摘要

IN 一定走索引吗?那当然了,不走索引还能全部扫描吗?好像之前有看到过什么Exist,IN走不走索引的讨论。但是好像看的太久了,又忘记了。哈哈,如果你也忘记了MySQL中IN是如何查询的,就来复习下吧。

问题

问题要从之前的统计店铺数关注人数说起

SELECT shop_id, count(user_Id) as attentionNumber
FROM shop_attention
WHERE shop_id IN
<foreach collection="shopIds" item="shopId" separator="," open="(" close=")">#{shopId}
</foreach>
GROUP BY shopId
复制代码

当时是从缓存的角度来分析如何进行优化。有兴趣看这篇微服务化后缓存怎么做

将这个查询收敛,应用端做了缓存后,确实没什么大问题了。但是随着店铺关注数的增加,慢SQL开始出现了

在我们的业务中,将100ms的SQL查询定义为慢查询,需要优化的。优化不了必须要控制查询频次。同时超过5s的数据库操作会被kill掉,防止拖垮整个数据库,导致相关应用都受到牵连。

该SQL执行时间耗时已经几百ms了,必须要优化了。阿里云对这个SQL的检测报告时

  1. 扫描行数和返回行数比例超过了100
  2. 使用了group_by函数,注意检查group_by是否用到了索引

分析

首先可以确定的是,group by 的shop_id字段肯定是建了索引的,那么扫描行数和返回行数比例为什么这么大呢?

先复习下分析查询语句的三大要素

  1. 响应时间,意思很明确,不多解释了
  2. 扫描行数 整个查询过程中扫描了多少行
  3. 返回行数 查询结果命中的行数 一般来说扫描行数和返回行数一样,是最好的,但是这是理想情况,事实并非如此。关联查询/范围排序查询时都会使得扫描行数大于返回行数。一般这个比例要控制在10以下,否则可能会有性能问题。

题外话,我一直觉得mysql explain的展示字段不如mongo的直观。mongo索引原理同mysql一样,有兴趣的可以看下Mongo Index分析

那么现在问题来了,为什么这个查询扫描行数/返回行数比例这么大呢。

那么就explain 一下了

实验1

SELECT shop_id, count(user_Id) as attentionNumber
FROM shop_attention
WHERE shop_id IN(1,2,3)
GROUP BY shopId
复制代码
type possible_keys key key_length ref rows Extras
range idx_shop idx_shop 8 null 16000 Using index condition

和我预想的一样,类型是range走了shopId的索引,没毛病。那怎么扫描行数/返回行数比例这么大的。

实验2

再试一把,将IN的范围增大了。

SELECT shop_id, count(user_Id) as attentionNumber
FROM shop_attention
WHERE shop_id IN(1,2,3,4,5,6,7,8,9)
GROUP BY shopId
复制代码
type possible_keys key key_length ref rows Extras
index idx_shop idx_shop 8 null 303000 Using where

结果不一样了,类型是index,也就是没有走范围扫描,而是走的是索引扫描。

实验3

强制走索引

SELECT shop_id, count(user_Id) as attentionNumber
FROM shop_attention force index(idx_shop)
WHERE shop_id IN(1,2,3,4,5,6,7,8,9)
GROUP BY shopId
复制代码
type possible_keys key key_length ref rows Extras
range idx_shop idx_shop 8 null 29000 Using Index Condition

这时候走的是范围扫描,而不是索引扫描。但是你会发现这次的执行时间并不没有比·上一次的执行时间短

mysql对这个查询进行了优化,使其不走范围扫描。而是走的是索引扫描。那么必然会随着IN的条件越来越多, 扫描的行数越多,执行的时间越长。

所以这个问题的优化的办法呢,就是在应用端做切割,分批去查。每次查N个,保证每次的查询都很快。

总结

根据实际的情况,需要控制IN查询的范围。原因有以下几点

  1. IN 的条件过多,会导致索引失效,走索引扫描
  2. IN 的条件过多,返回的数据会很多,可能会导致应用堆内内存溢出。

所以必须要控制好IN的查询个数

关注公众号【方丈的寺院】,第一时间收到文章的更新,与方丈一起开始技术修行之路

转载于:https://juejin.im/post/5d06331f518825664b6ce09d

SQL IN 一定走索引吗?相关推荐

  1. mysql查看sql语句是否走索引

    在查询语句前加上explain: 返回如图所示, 几个字段含义分别是: id // 选择标识符 select_type // 表示查询的类型 table // 输出结果集的表 partitions / ...

  2. 查询没有走索引_MySQL 如何正确的使用索引

    学习索引,主要是写出更快的sql,当我们写sql的时候,需要明确的知道sql为什么会走索引?为什么有些sql不走索引?sql会走那些索引,为什么会这么走?我们需要了解其原理,了解内部具体过程,这样使用 ...

  3. oracle强制走索引_实验验证:Oracle聚簇因子对索引使用的影响

    [引言] 本文基于如下文章进行的实验,讲述聚簇因子对SQL索引的影响. 链接如下: https://www.modb.pro/db/40283 一张表上有索引,sql在执行的时候却不走索引的原因有很多 ...

  4. oracle怎么条件强制走索引,如何让oracle的select强制走索引

    大多数情况下,oracle数据库内置的查询优化策略还是很成功的,但偶尔也有犯2的时候,即使有索引,也会做全表扫描,可以参考以下语句的写法,强制让select语句使用索引 CREATE OR REPLA ...

  5. mysql左模糊 走索引_mysql的模糊查找是否走索引问题

    2019独角兽企业重金招聘Python工程师标准>>> 在数据库中索引对于查找是非常有用的,楼主做了两个实验,插入数据的时候非常慢,楼主是这样实验的: 一:数据库列的索引 ①:首先执 ...

  6. mysql优化说出九条_技术分享 | MySQL 优化:为什么 SQL 走索引还那么慢?

    原标题:技术分享 | MySQL 优化:为什么 SQL 走索引还那么慢? 背景 2019-01-11 9:00-10:00 一个 MySQL 数据库把 CPU 打满了. 硬件配置:256G 内存,48 ...

  7. sql语句分析是否走索引_SQL语句无法走索引的一些情况分析及语句改写思路

    因为优化器还不够强大,还有很多限制,或者因为一些逻辑原因,分析认为SQL要走索引比较好,但是事实却无法正确利用索引.这时候,除了给ORACLE需要的统计信息之外,写的SQL必须要能够给优化器足够多的额 ...

  8. SQL 优化之该走索引却不走索引的分析

    分析案例: 1.走rule很快,但是收集了执行计划后却很慢 SQL> create table test(id int); 表已创建. SQL> insert into test sele ...

  9. sql语句分析是否走索引_mysql sql语句执行时是否使用索引检查方法

    在日常开发中,使用到的数据表经常都会有索引,这些索引可能是开发人员/DBA建表时创建的,也可能是在使用过程中新增的.合理的使用索引,可以加快数据库查询速度.然而,在实际开发工作中,会出现有些sql语句 ...

最新文章

  1. dagger2 注入_使用Dagger 2在GWT中进行依赖注入
  2. Spring MVC和Thymeleaf:如何从模板访问数据
  3. Python数模笔记-模拟退火算法(3)整数规划问题
  4. AJAX 中Sys.WebForms.PageRequestManager的事件激发顺序
  5. C# 循环语句 for
  6. 共享充电宝还在打仗,支付宝已经笑了
  7. DataGuard切换(主库为Rac+备库为Rac)
  8. 软件架构-接口隔离原则
  9. 2017-2018-2 1723《程序设计与数据结构》每周成绩 (更新完毕)
  10. cocos2dx box2d使用(一)
  11. java 集合的并交差_java中计算集合的交差并集示例代码
  12. 爬取34万专栏文章:304篇10K+高赞文章汇总
  13. MaXmaPLe v1.0 for v0.62冒险岛服务端发布
  14. 阿里、华为登顶商科工科最具吸引力雇主;国家电网、京东方等入选全国企业科技创新百强 | 美通企业日报...
  15. 2021最新Spring Security知识梳理
  16. Unable to create/open lock file: /var/lib/mongodb/mongod.lock errno:13 Permission denied Is a mong..
  17. YOLOv7默默更新了Anchor-Free | 无痛再涨1.4mAP
  18. SAR舰船数据集----SSDD
  19. 终稿:教材管理系统与教学评估系统
  20. 微信头像下载并上传到阿里云OSS,PHP文件上传到阿里云OSS简单代码(OSS文件上传,微信头像下载,CURL下载文件,微信头像链接过期)

热门文章

  1. Redis的字典扩容与ConcurrentHashMap的扩容策略比较
  2. 2017校赛 问题 F: 懒人得多动脑
  3. Hibernate 缓存机制
  4. C++100w个数中找出最大的前K个数
  5. FZU1669 Right-angled Triangle【毕达哥拉斯三元组】
  6. linux系统安装后优化
  7. MySQL学习(二)复制
  8. 【考试认证专场】大牛带你全面掌握学习技巧,攻克考试难题(8.2-8.6精品课程限时特惠)...
  9. React.js 小书 Lesson14 - 实战分析:评论功能(一)
  10. 数据库索引类型及实现方式