SQL IN 一定走索引吗?
摘要
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的检测报告时
- 扫描行数和返回行数比例超过了100
- 使用了group_by函数,注意检查group_by是否用到了索引
分析
首先可以确定的是,group by 的shop_id字段肯定是建了索引的,那么扫描行数和返回行数比例为什么这么大呢?
先复习下分析查询语句的三大要素
- 响应时间,意思很明确,不多解释了
- 扫描行数 整个查询过程中扫描了多少行
- 返回行数 查询结果命中的行数
一般来说扫描行数和返回行数一样,是最好的,但是这是理想情况,事实并非如此。关联查询/范围排序查询时都会使得扫描行数大于返回行数。一般这个比例要控制在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查询的范围。原因有以下几点
- IN 的条件过多,会导致索引失效,走索引扫描
- IN 的条件过多,返回的数据会很多,可能会导致应用堆内内存溢出。
所以必须要控制好IN的查询个数
关注公众号【方丈的寺院】,第一时间收到文章的更新,与方丈一起开始技术修行之路

SQL IN 一定走索引吗?的更多相关文章
- sql查询未走索引问题分析之查询数据量过大
前因: 客户咨询,有一个业务sql(代表经常被执行且重要),全表扫描在系统占用资源很高(通过ash报告查询得到信息) 思路: 1.找到sql_text,sql_id 2.查看执行计划 3.查询sql涉 ...
- 以通配符(%)开始的like字符串,走索引
在对oracle的SQL优化过程中经常会遇到[like'%abc']破坏索引的问题,但是如果真有此类需求,该如何在不破坏索引的基础上进行查询呢. [sql] view plain copy sys@m ...
- 这个大表走索引字段查询的 SQL 怎么就成全扫描了,我TM人傻了
今天收到运营同学的一个 SQL,有点复杂,尤其是这个 SQL explain 都很长时间执行不出来,于是我们后台团队帮忙解决这个 SQL 问题,却正好发现了一个隐藏很深的线上问题. select a. ...
- SQL Server-聚焦过滤索引提高查询性能(十)
前言 这一节我们还是继续讲讲索引知识,前面我们讲了聚集索引.非聚集索引以及覆盖索引等,在这其中还有一个过滤索引,通过索引过滤我们也能提高查询性能,简短的内容,深入的理解,Always to revie ...
- Sql Server优化之索引提示----我们为什么需要查询提示,Sql Server默认情况下优化策略选择的不足
环境: Sql Server2012 SP3企业版,Windows Server2008 标准版 问题由来: 最近在做DB优化的时候,发现一个存储过程有非常严重的性能问题, 由于整个SP整体逻辑是一个 ...
- mysql中关于关联索引的问题——对a,b,c三个字段建立联合索引,那么查询时使用其中的2个作为查询条件,是否还会走索引?
情况描述:在MySQL的user表中,对a,b,c三个字段建立联合索引,那么查询时使用其中的2个作为查询条件,是否还会走索引? 根据查询字段的位置不同来决定,如查询a, a,b a,b, ...
- SQL Server 优化---为什么索引视图(物化视图)需要with(noexpand)强制查询提示
本文出处:http://www.cnblogs.com/wy123/p/6694933.html 第一次通过索引视图优化SQL语句,以及遇到的一些问题,记录一下. 语句分析 最近开发递交过来一个查询统 ...
- MySQL实现强制查询走索引和强制查询不缓存
0.表结构如下:(包含两个索引) Create Table: CREATE TABLE `user` ( `userID` ) NOT NULL, `userCode` ) DEFAULT NULL, ...
- SQL Server-聚焦过滤索引提高查询性能
前言 这一节我们还是继续讲讲索引知识,前面我们讲了聚集索引.非聚集索引以及覆盖索引等,在这其中还有一个过滤索引,通过索引过滤我们也能提高查询性能,简短的内容,深入的理解,Always to revie ...
随机推荐
- https抓包 Fiddler
打开Fiddler https抓包 安装证书 查看证书 打开Windows程序certmgr.msc 查找Fiddler证书 查看Fiddler证书是否安装成功 测试连接 使用Google Chrom ...
- JavaScript函数式编程究竟是什么?
摘要: 理解函数式编程. 作者:前端小智 原文:JS中函数式编程基本原理简介 Fundebug经授权转载,版权归原作者所有. 在长时间学习和使用面向对象编程之后,咱们退一步来考虑系统复杂性. 在做了一 ...
- Linux内核编程、调试技巧小集【转】
转自:https://www.cnblogs.com/arnoldlu/p/7152488.html 1. 内核中通过lookup_symbol_name获取函数名称 内核中很多结构体成员是函数,有时 ...
- 如何在docker镜像里安装pycuda和numba?
其实,安装numba还好,直接pip install numba就可以. 但pycuda就不那么友好了. 默认安装时,可能会报如下错误: src/:: fatal error: curand.h: N ...
- pytest文档30-功能用例与自动化用例完美对接(allure)
前言 做自动化做久了,经常会思考一个问题,到底别人是怎么做的自动化,跟自己的有啥不一样,看过不少书和资料,都是停留在demo的层面. 真正把自动化做的好的大牛又不屑于分享自己的劳动成果,所以大部分情况 ...
- day23_7.29 多态和类的内置方法
一.多态 在现实生活中,多态也会体现.如对于水这种物质,有固态:冰,液态:常态,气态:水蒸气, 在程序中,其官方定义是:多个不同对象可以相应同一方法,产生不同的结果. 而在python中,多态不是一个 ...
- woocommerce如何隐藏SKU
有时我们不想在woocommerce网站前台显示SKU,如下图所示,因为sku一多整个排版可能会乱,那么要如何隐藏sku呢?随ytkah一起来看看 在当前主题的function.php文件中加入如下代 ...
- USACO Stock Market
洛谷 P2938 [USACO09FEB]股票市场Stock Market 洛谷传送门 JDOJ 2625: USACO 2009 Feb Gold 2.Stock Market JDOJ传送门 题目 ...
- LG2852/BZOJ1717 「USACO2006DEC」Milk Patterns 离散化+后缀数组
问题描述 LG2852 题解 字符串性质:字符串\(s\)的每个字串等于每个后缀的所有前缀 对输入的东西离散化,然后把数值看做\(\mathrm{ASCII}\)后缀排序 二分答案,二分长度. 显然一 ...
- hive数据库从文件插入数据得到结果NULL?
今天第一次接触hive这个东东,跟着教程走,当把本地文件的数据装载到新建的hive的表中时,得到的结果是NULL,如图: 也不知道为什么,初次接触,对它的这个构造还不是很熟悉,看一下建表语句: 解决: ...