MySQL中的in+子查询应该如何优化

这篇具有很好参考价值的文章主要介绍了MySQL中的in+子查询应该如何优化。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

☆* o(≧▽≦)o *☆嗨~我是小奥🍹
📄📄📄个人博客:小奥的博客
📄📄📄CSDN:个人CSDN
📙📙📙Github:传送门
📅📅📅面经分享(牛客主页):传送门
🍹文章作者技术和水平有限,如果文中出现错误,希望大家多多指正!
📜 如果觉得内容还不错,欢迎点赞收藏关注哟! ❤️

MySQL中的in+子查询应该如何优化

MySQL 4.1引入了对子查询的支持,即嵌套在其他查询中的查询。

一、为什么需要子查询

比如给定一个订单信息查询的场景:

订单存储在两个表中:

  • 对于包含订单号、客户ID、订单日期的每个订单,orders表存储一行。
  • 各订单的物品存储在相关的orderitems表中。

orders表不存储客户信息,它只存储客户的ID。实际的客户信息存储在customers表中。

假如需要列出订购物品TNT2的所有客户,应该怎样检索?

  • 检索包含物品TNT2的所有订单的编号。
  • 检索具有前一步骤列出的订单编号的所有客户的ID。
  • 检索前一步骤返回的所有客户ID的客户信息。

上述每个步骤都可以单独作为一个查询来执行。可以把一条SELECT语句返回的结果用于另一条SELECT语句的WHERE子句。

两条SQL如下:

# 检索订单编号,假设检索结果是20005,20007
SELECT order_num FROM orderitems WHERE prod_id = 'TNT2';
# 检索对应订单编号的客户的id,假设检索结果是10004,10005
SELECT cust_id FROM orders WHERE order_num IN (20005,20007);

如果使用子查询,那么就可以组合如下:

SELECT cust_id FROM orders WHERE order_num IN (SELECT order_num FROM orderitems WHERE prod_id = 'TNT2');

其实,这两种SQL的结果是一样的,在WHERE子句中使用子查询能够编写出功能很强并且很灵活的SQL语句。

二、IN + 子查询优化

下面我们就来分析一下 IN + 子查询 的执行计划,以及如何去优化它。

2.1 IN + 子查询

子查询与IN结合使用时,通常通过子查询查询出某个表单列的值,然后作为外层的SELECT的IN查询的数据源,如下:

mysql> select id, name, phone from user 
mysql> where id in (select user_id from user_realname where name = 'zhangsan');
+--+--------+-----------+
|id|name    |phone      |
+--+--------+-----------+
|1 |zhangsan|13511223453|
+--+--------+-----------+

下面我们通过执行计划Explain来分析一下该SQL:

+--+------------+-------------+----------+------+-------------+-------+-------+-------------------+----+--------+-----------+
|id|select_type |table        |partitions|type  |possible_keys|key    |key_len|ref                |rows|filtered|Extra      |
+--+------------+-------------+----------+------+-------------+-------+-------+-------------------+----+--------+-----------+
|1 |SIMPLE      |<subquery2>  |null      |ALL   |null         |null   |null   |null               |null|100     |Using where|
|1 |SIMPLE      |user         |null      |eq_ref|PRIMARY      |PRIMARY|4      |<subquery2>.user_id|1   |100     |null       |
|2 |MATERIALIZED|user_realname|null      |ALL   |null         |null   |null   |null               |4   |25      |Using where|
+--+------------+-------------+----------+------+-------------+-------+-------+-------------------+----+--------+-----------+

分析:

  • 对于外层SELECT对应用户表user的每一行数据都要执行一次这个子查询,而这个子查询是需要返回一个数据集合而不是单条数据,然后再判断外层SELECT的当前数据行的该列的值是否在这个集合中,类似于O(N)的线性时间复杂度

2.2 EXISTS

mysql> select id, name, phone from user
mysql> where exists 
mysql> (select * from user_realname where user.id = user_realname.user_id and name = 'zhangsan');

+--+--------+-----------+
|id|name    |phone      |
+--+--------+-----------+
|1 |zhangsan|13511223453|
+--+--------+-----------+

下面我们通过执行计划Explain来分析一下该SQL:

+--+------------+-------------+----------+------+-------------+-------+-------+-------------------+----+--------+-----------+
|id|select_type |table        |partitions|type  |possible_keys|key    |key_len|ref                |rows|filtered|Extra      |
+--+------------+-------------+----------+------+-------------+-------+-------+-------------------+----+--------+-----------+
|1 |SIMPLE      |<subquery2>  |null      |ALL   |null         |null   |null   |null               |null|100     |Using where|
|1 |SIMPLE      |user         |null      |eq_ref|PRIMARY      |PRIMARY|4      |<subquery2>.user_id|1   |100     |null       |
|2 |MATERIALIZED|user_realname|null      |ALL   |null         |null   |null   |null               |4   |25      |Using where|
+--+------------+-------------+----------+------+-------------+-------+-------+-------------------+----+--------+-----------+

分析:

  • 执行计划与IN差不多,外层SELECT的type都是ALL,即全表扫描,但是EXISTS的执行过程与IN不一致
  • 对于EXISTS而言,外层SELECT对应的用户表user也参与到了子查询的SQL中,即user.id = user_realname.user_id,故如果子查询的结果不为空,即存在数据,则外层SELECT对应的user表的当前数据行肯定是符合要求的,故该子查询实际上并不返回任何数据,而是返回值True或False,不需要与IN一样返回一个数据集合。
  • 而对外层SELECT来说,通过EXISTS判断子查询返回的boolean值True或者False来判断当前数据行是否符合要求,故时间复杂度为常量级别O(1)

2.1 JOIN

mysql> select user.id, user.name, user.phone from user
mysql> join user_realname
mysql> on user.id = user_realname.user_id
mysql> where user_realname.name = 'zhangsan';

+--+--------+-----------+
|id|name    |phone      |
+--+--------+-----------+
|1 |zhangsan|13511223453|
+--+--------+-----------+

下面我们通过执行计划Explain来分析一下该SQL:

+--+-----------+-------------+----------+------+-------------+-------+-------+-----------------------------------+----+--------+-----------+
|id|select_type|table        |partitions|type  |possible_keys|key    |key_len|ref                                |rows|filtered|Extra      |
+--+-----------+-------------+----------+------+-------------+-------+-------+-----------------------------------+----+--------+-----------+
|1 |SIMPLE     |user_realname|null      |ALL   |null         |null   |null   |null                               |4   |25      |Using where|
|1 |SIMPLE     |user         |null      |eq_ref|PRIMARY      |PRIMARY|4      |leadnews_user.user_realname.user_id|1   |100     |null       |
+--+-----------+-------------+----------+------+-------------+-------+-------+-----------------------------------+----+--------+-----------+

分析:

  • 子查询不管是使用IN还是EXISTS,对外层SELECT对应的数据表均需要进行全表扫描,并且对于每行数据都需要执行一次子查询,所以如果该数据行表很大,则需要执行大量的子查询,即可能出现“大表驱动小表”,从而产生性能问题。
  • 对于JOIN而言,由于可以通过“小表驱动大表”,所以可以一定程度上优化子查询。

三、总结

对于IN+子查询的SQL方式:文章来源地址https://www.toymoban.com/news/detail-806370.html

  • 使用EXIST结合子查询效率会更高;
  • 建议使用JOIN来优化。

到了这里,关于MySQL中的in+子查询应该如何优化的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 在MySQL执行查询时出现了慢查询情况,应该如何解决?

    MySQL是一种流行的关系型数据库管理系统,但在处理大量数据时,可能会出现慢查询问题。通过使用EXPLAIN命令、慢日志和监视工具等技术,可以诊断出导致MySQL慢查询问题的原因。优化措施包括创建索引、使用联合查询、优化数据库服务器配置、减少查询返回数据的数量和优

    2024年02月11日
    浏览(54)
  • MySQL查询性能优化——SQL优化(四)

      目录 1、批量插入数据 1.1 linux环境下 1.1.1 开启文件读取 1.1.2 load数据 1.2 windows环境下 2、order by优化 2.1 最左前缀 3、group by 3.1 最左前缀 4、count优化 5、or条件优化   在上一期说到索引的使用,这期来聊一下SQL优化,也是平常写SQL的时候常用到的。 在前几期也有聊到过批量插

    2024年02月19日
    浏览(41)
  • mysql高级三:sql性能优化+索引优化+慢查询日志

    内容介绍 单表索引失效案例 0 、思考题: 如果把 100 万数据插入 MYSQL ,如何提高插入效率 (1)关闭自动提交,只手动提交一次 (2)删除除主键索引外其他索引 (3)拼写mysql可以执行的长sql,批量插入数据 (4)使用java多线程 (5)使用框架,设置属性,实现批量插入 1、

    2024年02月12日
    浏览(47)
  • mysql:IN最多只能查询1000个,如果要一次性查询出来,使用以下sql实现

    1、 if test=\\\"(index % 999) == 998\\\" :余数等于998,将,置为NULL SELECT mph.PO_HEADER_ID, mph.PO_NUMBER, mid.INSTRUCTION_DOC_STATUS, mid.INSTRUCTION_DOC_NUM FROM mt_po_header mph LEFT JOIN mt_instruction mi ON mi.SOURCE_ORDER_ID = mph.PO_HEADER_ID LEFT JOIN mt_instruction_doc mid ON mid.INSTRUCTION_DOC_ID = mi.SOURCE_DOC_ID WHERE mph.TENANT_ID = 7 AND

    2023年04月09日
    浏览(39)
  • MySQL 联表查询重复数据并删除(子查询删除记录) SQL优化

    数据库表介绍: table_a :主表(小表,表数据不可重复) table_b :流水表(大表,记录审核流水数据) 注:两表表结构大致一致,流水表增加一个审核状态的字段 业务逻辑: 主表保存唯一数据,流水表记录审核流水数据,用于后续展示,并在审核成功后插入主表,在插入流

    2023年04月08日
    浏览(48)
  • MySQL 中的 SQL 查询性能调优

            通过 MySQL 中的索引加速 SQL 查询。安装、分析查询并使用存储过程以获得最佳结果。         在本文中,我们将了解索引表列如何帮助提高 SQL 查询的快速响应时间。我们将介绍安装 MySQL、创建存储过程、分析查询以及了解索引的影响的步骤。         我在

    2024年02月12日
    浏览(34)
  • 玩转MySQL数据库之SQL优化之慢查询

    本系列为:MySQL数据库详解,为千锋资深教学老师独家创作,致力于为大家讲解清晰MySQL数据库相关知识点,含有丰富的代码案例及讲解。如果感觉对大家有帮助的话,可以【关注】持续追更~ 文末有本文重点总结,技术类问题,也欢迎大家和我们沟通交流! 从今天开始本系列

    2024年02月06日
    浏览(69)
  • MySQL 如何优化慢查询?

    在日常开发中,我们往往会给表加各种索引,来提高 MySQL 的检索效率。 但我们有时会遇到明明给字段加了索引,并没有走索引的Case。 进而导致 MySQL 产生慢查询。 严重场景下,甚至出现主从延迟、数据库拖垮的极端事故。 本文梳理出索引失效的几种常见场景给大家参考。

    2024年02月05日
    浏览(31)
  • Mysql如何优化数据查询方案

    mysql做读写分离 读写分离是提高mysql并发的首选方案。 Mysql主从复制的原理 mysql的主从复制依赖于binlog,也就是记录mysql上的所有变化并以二进制的形式保存在磁盘上,复制的过程就是将binlog中的数据从主库传输到从库上。 主从复制过程详细分为3个阶段: 第一阶段:主库写

    2024年02月21日
    浏览(34)
  • 【MySQL】sql如何优化?

    (1)通过SQL监控、请求、日志等找出耗时的SQL语句; (2)使用Explain方式查看SQL耗时的具体原因; (3)根据实际情况解决:索引、缓存、左右连接 select_type:简单查询or复杂查询?simple、primary、subquery、deriveer、union。 type:SQL关联类型, system const eq_ref ref range index All 。一般

    2024年02月07日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包