掌柜又随手刷了一道力扣数据库题,这次是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查询两个不同列。