当前位置: 首页 > 面试题库 >

MySQL是否会自动优化子查询?

颛孙嘉玉
2023-03-14
问题内容

我想运行以下查询:

-- Main Query    
SELECT COUNT(*) FROM table_name WHERE device_id IN 
     (SELECT DISTINCT device_id FROM table_name WHERE NAME = 'SOME_PARA')

以下查询(来自主查询的子查询):

SELECT DISTINCT device_id FROM table_name WHERE NAME = 'SOME_PARA'

在7秒内执行,从210万行的表中产生了2691行。

我在上面触发了 主查询 ,并且在等待5分钟以上之后它仍在执行。

最后,我分别执行了子查询,从结果中提取了2691条记录,执行了以下查询:

-- Main Query (improvised)    
SELECT COUNT(*) FROM table_name WHERE device_id IN 
     ("device_id_1", "device_id_2", ....., "device_id_2691")

令人惊讶的是,这在40秒内给了我一个答案。

是什么赋予了?为什么MySQL不使用我使用的相同技术并迅速给出答案?难道我做错了什么?


问题答案:

不幸的是,MySQL在用IN优化子查询方面不是很擅长。这来自MySQL文档:

IN的子查询优化不如=运算符或IN(value_list)运算符有效。

IN子查询性能较差的典型情况是,子查询返回的行数很少,而外部查询返回的行数要与子查询结果进行比较。

问题在于,对于使用IN子查询的语句,优化器将其重写为相关子查询。考虑以下使用不相关子查询的语句:

在t1的SELECT … FROM t1.a IN(从t2的SELECT b)中;

优化器将语句重写为相关的子查询:

从t1存在的地方选择…(从t2 t2.b = t1.a的地方选择1);

如果内部查询和外部查询分别返回M和N行,则执行时间将变成O(M脳N)的顺序,而不是像不相关子查询那样的O(M + N)。

暗示是,IN子查询可能比使用IN(value_list)运算符编写的查询慢得多,该运算符列出了子查询将返回的相同值。

尝试改用JOIN。

因为MySQL从内到外起作用,所以有时您可以通过将子查询包装在另一个子查询中来欺骗MySQL,如下所示:

SELECT COUNT(*) FROM table_name WHERE device_id IN
     (SELECT * FROM (SELECT DISTINCT device_id FROM table_name WHERE NAME = 'SOME_PARA') tmp)

这是JOIN解决方案:

SELECT COUNT(DISTINCT t2.id) FROM table_name t1
  JOIN table_name t2
    ON t2.device_id = t1.device_id
  WHERE t1.NAME = 'SOME_PARA'

请注意,我从内而外开始。



 类似资料:
  • 主要内容:概述,一、关联查询优化,1.左(右)外连接,2.内连接,3.JOIN语句原理,4.JOIN小结,5.Hash Join,二、子查询优化,三、排序优化,四、GROUP BY优化,五、优先考虑覆盖索引,六、使用前缀索引,七、索引下推ICP,八、其他查询优化,1.COUNT(*)与COUNT(具体字段)效率,2.不使用SELECT *,3.LIMIT 1优化,4.多使用commit概述 数据库调优的方式有多种: 建立索引、充分利用到索引、不让索引失效 对SQL语句进行优化 调优如缓冲、线程数

  • 本文向大家介绍对MySQL子查询的简单改写优化,包括了对MySQL子查询的简单改写优化的使用技巧和注意事项,需要的朋友参考一下 使用过oracle或者其他关系数据库的DBA或者开发人员都有这样的经验,在子查询上都认为数据库已经做过优化,能够很好的选择驱动表执行,然后在把该经验移植到mysql数据库上,但是不幸的是,mysql在子查询的处理上有可能会让你大失所望,在我们的生产系统上就由于碰到了这个问

  • 问题内容: 一个供您所有MySQL专家使用的技巧:-) 我有以下查询: 订单表= 80,900行 产品表= 125,389行 o.id和p.order_id已建立索引 该查询大约需要6秒钟才能完成-太长了。我正在寻找一种优化它的方法,可能使用临时表或其他类型的联接。恐怕我对这两个概念的理解还很有限。 谁能建议我优化此查询的方法? 问题答案: 首先,我将使用其他样式的语法。 已经有20年的睡眠时间了

  • 问题内容: 这就是整个查询… 如果… 和… 有明显的理由吗? 正在服用? 扩展说明 问题答案: 您可以始终使用EXPLAIN或EXPLAIN EXTENDED 来查看MySql对查询所做的操作 您也可以用稍微不同的方式编写查询,是否尝试过以下方法? 看看效果如何会很有趣。我希望它会更快,因为目前,我认为MySql将为您拥有的每个节目运行内部查询1(这样一个查询将运行多次。联接应该更有效。) 如果希

  • 本文向大家介绍Mysql慢查询优化方法及优化原则,包括了Mysql慢查询优化方法及优化原则的使用技巧和注意事项,需要的朋友参考一下 1、日期大小的比较,传到xml中的日期格式要符合'yyyy-MM-dd',这样才能走索引,如:'yyyy'改为'yyyy-MM-dd','yyyy-MM'改为'yyyy-MM-dd'【这样MYSQL会转换为日期类型】 2、条件语句中无论是等于、还是大于小于,WHERE

  • 本文向大家介绍MySQL的子查询及相关优化学习教程,包括了MySQL的子查询及相关优化学习教程的使用技巧和注意事项,需要的朋友参考一下 一、子查询 1、where型子查询 (把内层查询结果当作外层查询的比较条件) 2、from型子查询 (把内层的查询结果供外层再次查询) #用子查询查出挂科两门及以上的同学的平均成绩 思路: 3、exists型子查询 (把外层查询结果拿到内层,看内层的查询是否成立)