Mysql面试题分享十三:Or和In是否会用到索引?

关于MySQL中in和in走不走索引的问题---具体情况得看优化器自己决定,但大致的规律是:in或or的数据量占比越大越可能不走,比如几百条数据我in上十来条他是会走索引的。

1.MySQL in 会用到索引吗?


        不一定,要看情况,具体是由MySQL优化器内部决定是全表扫描还是索引查找,用效率较高的一种方式。

针对索引字段的唯一性不高的情况下(索引的"区分度"低),优化器可能会选择全表扫描,而不是走索引。这可能是因为等值查询符合条件的记录太多了,导致了mysql认为全表扫描比用索引查找更快。
比如你对唯一性不高的字段(如性别:男/女)加了索引,这样通过索引去查找可能还需回表,还不如直接全表扫描!
若in中的数据量较大时,基本就不走索引了。如果你索引字段是一个unique,in可能就会用到索引。
如果你一定要用索引,可以用 force index。可能也和MySQL版本有关(5.6以后有做in的查询优化)。
        注:如果是 5.5 之前的版本确实不会走索引的,在 5.5 之后的版本,MySQL 做了优化。MySQL 在 2010 年发布 5.5 版本中,优化器对 in 操作符可以自动完成优化,针对建立了索引的列可以使用索引,没有索引的列还是会走全表扫描。


2.MySQL or 会用到索引吗?


        不一定,要看情况。or走索引与否,还和优化器的预估有关,就算连接条件都设置了索引,也可能因为回表导致索引失效。

        索引优化器的存在,就是找到一个索引扫描行数最少的方案去执行语句。那么扫描行数怎么来判断的?是逐行统计数据表的数据吗?其实并不是,而是根据统计信息来预估的值,这个统计信息就是我们常说的索引的“区分度”。

        显然,一个索引上不同的值越多,这个索引的区分度就越好。我们把一个索引上不同的值的个数,称之为 "索引基数"。也就是说,基数越大,索引的区分度就越好,执行查询的行数就越少。如何查看索引基数呢?使用 show index from 表名,其中cardinality字段显示的就是索引的基数。

        扩展:MySQL 是怎样得到索引基数的呢?不感兴趣的小伙伴可以飘过啦~
        索引基数 = 采样统计*页数。采样统计就是避免把整张表取出来一行行统计做精准计算,以免消耗系统性能。在采样统计时,InnoDB默认会选择 N 个数据页,统计这些页面上的 "对应索引字段" 上不同值的个数,得到一个平均值,然后用平均值乘以这个索引的页面数,就得到了这个索引的基数。统计信息不是固定不变的,他会随着数据表的变化而变化。当变更的数据行数超过 1/M 的时候,会自动触发重新做一次索引统计。

        建议:在使用前最好还是先用 explain 来试试到底sql语句走不走索引,然后选择较优的sql。

3.总结

分三中情况进行测试,分别是:

  第一种情况:in和or所在列为主键的情形

  第二种情况:in和or所在列创建有索引的情形

  第二种情况:in和or所在列没有索引的情形

  最后得出的结论如下:

1、in或or在字段有添加索引的情况下,查询很快,两者查询速度没有什么区别;

2、in或or在字段没有添加索引的情况下,所连接的字段越多(1or2or3or4or......),or比in的查询效率低很多。

在StackOverFlow里,我也搜到了一些答案,典型的如下:

  有人做了实验,通过他的对比,也是In的效率更高。

  还有这个回答:说是引用至《高性能MySQL》

  大致翻译下,意思是说:

在很多数据库里,In和or是等价的,因为他们逻辑是相等的。但是,在MySQL中会对 in 中的列表排序,排序用的是二分查找来判断是否在列表中。in 的时间复杂度是O(logn) ,而or的时间复杂度是O(n),这就意味着In的效率更高。

  另外还有人说范围查找比 in 效率还高。

官方文档

  地址:https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_in

  简单翻一下:列表中的值被排序,expr的搜索使用二进制搜索完成,这使得IN()操作非常快速。

  可以看到官方文档和上面的解释非常类似,效率很高。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

之乎者也·

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值