背景

最近慢sql 性能优化 发现一个调用频率高的sql 使用 in 子查询,导致外层全表扫描的问题?
为什么会产生这样的问题?特别强调在优化的使用发现 使用in 和优化后的效果差距 300倍,可见全表扫描的效果可多厉害。 mysql 版本 5.6

参考

搜集了一下资料发现 https://www.cnblogs.com/wy123/archive/2017/06/28/7092194.html 这篇 文章特别像我们的场景,子查询中 查询一个条件,然后非常慢使用不上索引

实践

创建表

create table test_table2
(id int auto_incrementprimary key,pay_id int null,pay_time datetime null,other_col varchar(100) null
);create index test_table2_pay_id_indexon test_table2 (pay_id);

执行计划

explain extended select * from test_table2
where  pay_id in(select pay_id from test_table2where pay_id  > 800group by pay_idhaving count(pay_id) > 2);

从执行计划可以看出 先执行子查询(SUBQUERY), 然后扫描了全表的数据。

[{"id": 1,"select_type": "PRIMARY","table": "test_table2","partitions": null,"type": "ALL","possible_keys": null,"key": null,"key_len": null,"ref": null,"rows": 1010,"filtered": 100,"Extra": "Using where"},{"id": 2,"select_type": "SUBQUERY","table": "test_table2","partitions": null,"type": "range","possible_keys": "test_table2_pay_id_index","key": "test_table2_pay_id_index","key_len": "5","ref": null,"rows": 200,"filtered": 100,"Extra": "Using where; Using index"}
]

即使强制指定索引也没有用

explain extended select * from test_table2 force index(test_table2_pay_id_index)
where  pay_id in(select pay_id from test_table2where pay_id  > 800group by pay_idhaving count(pay_id) > 2);

为什么?

如果直接使用这种查询 (pay_id) in 常量

效率杠杠的,使用了索引 pay_id

explain  select * from test_table2 where pay_id in(800,900)

为什么没有命中索引?

子查询的结果是未知的,不能作为外层的索引判断 。【高版本mysql优化器应该会优化成连接查询】
以上就是利用,在SQL 查询语言执行流程中,优化器执行计划生成已经索引选择阶段,子查询的结果无法提供任何的判断依据,因此不能作为外层判断索引的依据,由此导致外层直接全表扫描了。具体可以参考一下 Mysql的查询流程。
MySql查询语句执行流程

如何改进

接改为连接查询非常快

explain extended
select * from test_table2 as t1inner join (select pay_id from test_table2where pay_id  > 800group by pay_idhaving count(pay_id) > 2)as tmp on tmp.pay_id =t1.pay_id;

总结

对于子查询慎用 in,常量情况下可以使用 in 涉及多表操作 in 最好使用 连接查询,性能差异可能几百倍。

mysql in 子查询无法使用索引全表扫描 慎用in相关推荐

  1. oracle查询不走索引全表扫描,使用索引快速全扫描(Index FFS)避免全表扫描的若干场景-Oracle...

    使用索引快速全扫描(Index FFS)避免全表扫描的若干场景 什么使用使用Index FFS比FTS好? Oracle 8的Concept手册中介绍: 1. 索引必须包含所有查询中参考到的列. 2. ...

  2. mysql join子查询_MySQL的多表join中,子查询伤不起啊!

    leader找到我,说下面的sql执行后cpu100%,但是这三张join的表数据量都在2W左右,不应该啊,是不是数据库服务器配置出了问题啊.sql如下: select a.excel_id, a.r ...

  3. mysql子查询走索引吗_MySQL中in子查询会导致无法使用索引问题(转)

    MySQL的测试环境 测试表如下 create tabletest_table2 ( idint auto_increment primary key, pay_idint, pay_timedate ...

  4. mysql什么情况会扫描所有_造成MySQL全表扫描的原因

    全表扫描是数据库搜寻表的每一条记录的过程,直到所有符合给定条件的记录返回为止.通常在数据库中,对无索引的表进行查询一般称为全表扫描:然而有时候我们即便添加了索引,但当我们的SQL语句写的不合理的时候也 ...

  5. 我说 SELECT COUNT(*) 会造成全表扫描,面试官让我回去等通知

    来自:码海 前言 上篇 SQL 进阶技巧(下) 中提到使用以下 sql 会导致慢查询 SELECT COUNT(*) FROM SomeTable SELECT COUNT(1) FROM SomeT ...

  6. 数据库CPU内存高以及全表扫描的原因

    哪些情况数据库全表扫描 1. 使用null做为判断条件 2. 左模糊查询Like %XXX% 3. 使用or做为连接条件 4. 使用in时(not in) 5.使用not in时 6.使用!=或< ...

  7. MYSQL避免全表扫描__如何查看sql查询是否用到索引(mysql)

    MYSQL避免全表扫描 1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引 2.应尽量避免在 where 子句中对字段进行 null 值判断,否 ...

  8. MYSQL的全表扫描,主键索引(聚集索引、第一索引),非主键索引(非聚集索引、第二索引),覆盖索引四种不同查询的分析...

    文章出处:http://inter12.iteye.com/blog/1430144 MYSQL的全表扫描,主键索引(聚集索引.第一索引),非主键索引(非聚集索引.第二索引),覆盖索引四种不同查询的分 ...

  9. 范围查找(比如日期范围)下查询出现全表扫描MySQL数据库索引失效

    范围查找(比如日期范围)下查询出现全表扫描MySQL数据库索引失效 当下MySQL数据库在多款数据库中脱颖而出,成为使用最广泛的数据库之一,这里我们来看看数据库索引上的一个问题.我们知道在数据量上去以 ...

最新文章

  1. 壁布接缝压条_墙布压条样板
  2. JS在浏览器中的执行机制
  3. java javac javap 命令使用简介
  4. POJ 2152 Fire(树形DP)
  5. windbg模拟器不准确现象
  6. [C++调试笔记]执行声明的读写文件操作
  7. 如何修改Vue打包后文件的接口地址配置
  8. fx 线程 弹窗_JFXPanel和FX Platform线程陷阱
  9. 基于Nokia S60的游戏开发之一
  10. django 自定义权限_如何对django api做权限限制
  11. Python文件夹copy器(多进程版)学习笔记
  12. David Pozar 微波工程读书笔记(一)
  13. 使用Python绘制淘宝商品评论词云图
  14. 冒泡排序 java代码实现
  15. ENVI_建模工具的使用——以“指数计算”批处理为例
  16. 2022 中国开发者影响力盛典暨 CSDN 企业生态汇在京举行
  17. 神经网络中单层神经元表示逻辑运算
  18. 计算机网络压线实验,实验一双绞线的制作山东大学计算机网络自考作业
  19. ISO 18184纺织品抗病毒活性的测定
  20. 【linux find命令】在目录中查找文件并删除文件

热门文章

  1. Python机器学习英文资源
  2. 鸿蒙升级后桌面背景底纹怎么弄,ps添加背景怎么弄
  3. c语言 100匹马 编程,编程,百马百担有关问题,有100匹马,驮100担货,大马驮三担,中马驮2担,两匹小马驮一担,求大、中、小各多少匹...
  4. RGB颜色与颜色名称对照表
  5. dtop: 一个基于减法的系统占用率及系统性能测量工具
  6. 第七次作业(团队项目——Alpha阶段开发)(3)
  7. 一个奇鸽船新体验:类似的木函软件
  8. 机器学习总结(九):梯度消失(vanishing gradient)与梯度爆炸(exploding gradient)问题
  9. Huawei 华为云 机器翻译调用 详解
  10. c开头英文语言,字母C开头的英文名