【问题标题】:What's the difference of the query with IN [duplicate]查询与 IN 有什么区别 [重复]
【发布时间】:2016-02-15 20:30:31
【问题描述】:

我有两个 MySQL 表,PostAccount

我将NodeJS 用于我的后端API,它会生成以下SQL 语句:

select `p`.`id` as `post_id`
from `Post` as `p` 
left join `Account` as `a` 
    on `a`.`id` = `p`.`author` 
where `p`.`id` in ('9', '10', '76', '77', 123) 
order by `p`.`id` asc

代码有效,问题是 SLOW!我尝试使用EXPLAIN 来检查发生了什么,它不使用INDEX

但是,后来我注意到 IN 子句混合了数字和字符串,所以我将 123 更改为 '123'EXPLAIN 再次,它使用 索引 现在:

那么,我的问题是当数字和 varchars 混合在 IN 中时会发生什么?

提前致谢

【问题讨论】:

  • Ricky,如果使用 (9, 10, 76, 77, 123),查询的性能会提高吗?如果使用 ('9', '10', '76', '77', '123'),性能有何变化?
  • 没有图片,谢谢。直接粘贴文本即可
  • @MuhammadMuazzam,该线程很有用且相关,但不回答操作的问题,因为它处理结果可能不一致的事实,因为使用了不同的比较运算符(MySQL 错误如果你问我)但是,这并不能解释这里的性能问题。很可能已经完成了 varchar 比较,但我不确定这一点,另一个问题并不暗示它。
  • p.id 列的数据类型?
  • 当使用相同的数据类型时,性能问题在上面得到解决

标签: mysql sql database optimization


【解决方案1】:

这个查询:

select `p`.`id` as `post_id`
from `Post` as `p` left join
     `Account` as `a` 
     on `a`.`id` = `p`.`author` 
where `p`.`id` in ('9', '10', '76', '77', 123) 
order by `p`.`id` asc;

对于where 子句,应该利用Post(id) 上的索引。它可能会也可能不会使用order by 的索引。

关于为什么不使用Post(id) 上的索引,我想到了两个原因。首先是类型转换。 in 列表由字符串组成。我的猜测是 id 是一个整数。有时,类型转换可以排除索引的使用。您可以通过将逻辑更改为:

where p.id in (9, 10, 76, 77, 123) 

第二个原因很简单,就是桌子太小了。 MySQL 在选择执行计划时确实考虑了基数。对于小表,全表扫描可能比索引更有效。在这种情况下,MySQL 应该始终使用覆盖索引。如果您想测试这种可能性,请在Posts(id, author) 上创建一个索引。这涵盖了查询,并且应该是优化器的首选。

【讨论】:

    【解决方案2】:

    如果您查看 MySQL 文档 How MySQL uses indexes,您会注意到以下声明:

    不同列的比较(将字符串列与 例如,时间或数字列)可能会阻止使用索引,如果 没有转换就不能直接比较值。对于给定的 数值列中的值,例如 1,它可能比较等于任何 字符串列中的值的数量,例如“1”、“1”、“00001”或 '01.e1'。这排除了对字符串列使用任何索引。

    因此,如果您在 IN-Statement 中混淆数据类型,可能会阻止索引的使用。

    【讨论】:

      猜你喜欢
      • 2016-05-06
      • 2017-01-09
      • 2016-03-26
      • 1970-01-01
      • 2018-09-20
      • 2013-09-05
      • 2013-02-27
      相关资源
      最近更新 更多