当前位置: 首页 > 科技观察

同事用这2个小技巧,让SQL语句效率提升了1000倍

时间:2023-03-14 00:08:50 科技观察

同事用这两个技巧,让SQL语句的效率提高了1000倍。1、允许字段的值为null,往往会导致灾难。首先,先准备一些数据,然后演示createtableanimal(idint,namechar(20),index(id))engine=innodb;index(id)为id字段创建一个索引,id和name都允许为null。然后插入4条数据,最后一条数据的id为.insertintoanimal(id,name)values(1,'cat');insertintoanimal(id,name)values(2,'dog');insertintoanimal(id,name)values(3,'pig');insertintoanimal(id,name)))values(null,'未命名的动物');此时表中的数据为此时我们查询表中有哪些动物的id!=1select*fromanimalwhereid!=1;结果如下:此时只找到两行数据,按道理应该是三行,但是没有匹配到id=null的那一行。您可能听说过null不等于任何其他值。从逻辑上讲,null!=1是正确的,但现实是残酷的,它只是不会匹配。所以,该字段的值是坚决不允许为null的,否则可能会出现意想不到的结果。反正这个坑我以前踩过,不知道你踩过没有?但是,如果有人将allow值设置为null怎么办?如果是这种情况,对于!=的搜索,您可以在后面添加一个oridisnull子句(注意,是null,而不是=null,因为id=null不会匹配值为null的行)。即:select*fromanimalwhereid!=1oridisnull;结果如下:2.尽量用union代替or(1)。刚才我们已经为id字段建立了索引。如果我们进行等价操作,我们一般使用索引操作。如果您不相信我,请看一下:解释select*fromanimalwhereid=1;结果如下:从执行计划可以看出id上的等效搜索可以使用索引查询(估计在你的预料之内),其中type=ref:表示使用非唯一索引rows=1:预测扫描一行(2),id为null会不会使用索引?答案是肯定的,如图explainselect*fromanimalwhereidisnull;其中type=ref:表示使用非唯一索引rows=1:predictivelyscanarow(3),那么问题来了,如果我们想找到id=1或者id=null的动物,我们可能会使用或者语句进行连接,即select*fromanimalwhereid=1oridisnull;那么这条语句会不会进入索引呢?索引,看执行计划就好了,如图explainselect*fromanimalwhereid=1oridisnull;其中:ref=ALL:表示全表扫描rows=4:通过执行计划预测扫描4行(而我们整个表只有4行记录)可以看出,使用or很有可能不使用索引,会大大降低查询率,所以一般不建议使用or子句来连接条件。那么如何解决呢?其实可以用union代替or,如下:select*fromanimalwhereid=1unionselect*fromanimalwhereidisnull。这时候索引会遍历两次,找到所有id=1且所有id=null的行,然后使用临时表存储最终结果,最后扫描临时表。