掌柜又随手刷了一道力扣数据库题,这次是595题👉:找大国。相信很多朋友都见过这个题,这题确实很简单,只要你SQL基础过关。

所以掌柜就简单提一下,此题主要考察知识点就是SQL中多条件的过滤。但是掌柜一如既往在自己解答后看其他人的题解时,发现了一个有趣的东西 – 就是大多数题解都写到👇:

这里使用Union连接两个查询语句的效率会优于使用OR方法???

真的是这样的吗???😮掌柜持怀疑态度❗

--------------------------------------------------------------------------我是一条怀疑分割线-----------------------------------------------------------------------------------

那么问题来了,为什么他们会说这里使用Union会优于OR呢?

掌柜翻阅了好些资料后发现,其实是因为大家都默认这样的想法:
即该表里面查询的这两列是索引列,而一旦使用OR查询遇到有索引的列,索引就会失效。

那么问题又来了:为什么他们说这里的索引会失效??? 可能有两个原因:

  • 一个原因:表的数据太少,查询优化器会觉得使用索引还不如全表扫描来的快。
  • 另一个原因:因为OR表示只需要满足一个条件即可,所以其中一列查询使用索引满足条件后,另一列就会出现索引失效,导致查询优化器本来要走B+树搜索快速定位的,结果却走了全表扫描。

--------------------------------------------------------------------------我是一条解惑分割线-----------------------------------------------------------------------------------

上面都是对大家觉得Union比OR更快的解答,但是掌柜在本地用MySQL自建Leetcode这题的表格后,所有字段都没加入索引,进行同样的查询:
然后再执行EXPLAIN查看后发现:

先解释一下表格中几个字段含义:

  • select_type:表示查询类型,这里第一个表格里面OR是走的普通查询(即没有用Union或者子查询)。而第二个表格里,id等于1的是PRIMARY(即最外层查询,也就是第一个查询的是它);id=2走的是UNION(即Union中第二个查询是它);最后一行表示Union的结果。
  • type :表示查询方式,ALL就是全表扫描,也是最不建议的方式。
  • ref:表示与索引比较的列,因为这里没有设置索引,所以是NULL。

从上图可以看出来,在没有索引又都是小表的时候,两个查询都是走的全表扫描,所以它们在查询时间上几乎没有很大差别,那么说Union优于OR就不成立!

--------------------------------------------------------------------------我是一条总结分割线-----------------------------------------------------------------------------------

那么肯定有朋友又要疑惑了,那下次再遇到这样的问题,到底是该用Union还是用OR呢?

其实这取决于表的大小以及表中字段有无索引:

  • 表小(一般<1000的数据可以理解为小表)且无索引,两种方式并没有太大差别;
  • 表小但是都有索引的时候,可以把两种方法都执行一遍,然后用Show Profiles或EXPLAIN查看哪种更优;
  • 表的数据量很大且查询字段都有索引的时候,一般情况下使用Union连接两个不同查询列的效率会优于使用OR查询两个不同列。

参考资料:
MySQL官网
SQL Performance UNION vs OR