这两个技巧不仅避免了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为1的动物select*fromanimalwhereid!=1;结果如下:此时只找到两行数据,按道理应该是三行,但是没有匹配到id=null的行。您可能听说过null不等于任何其他值。按道理null!=1是真的,但现实是残酷的,就是匹配不上。所以,该字段的值是坚决不允许为null的,否则可能会出现意想不到的结果。反正这个坑我以前踩过,不知道你踩过没有?但是如果有人设置了允许空值怎么办?如果是这种情况,您可以在!=搜索之后添加一个oridisnull子句(注意是isnull,而不是=null,因为id=null不会匹配值为null的行)。即select*fromanimalwhereid!=1oridisnull;结果如下:2.尽量用union代替or(1)。刚才我们已经为id字段建立了索引。如果我们进行等价操作,我们一般会使用索引操作。不信你看:explainselect*fromanimalwhereid=1;结果如下:从执行计划可以看出,id上的等价查找可以使用索引查询(估计在你的预料之内),其中type=ref:表示使用非唯一索引rows=1:Predictively扫描一行(2),id为null会不会去索引?答案是肯定的,如图explainselect*fromanimalwhereidisnull;其中type=ref:表示去非唯一索引rows=1:预测扫描行(3),那么问题来了,那么如果我们要找出id=1或者id=null的动物,我们可能会使用连接的or语句,即select*fromanimalwhereid=1oridisnull;那么这条语句会不会进入索引呢?有没有索引,看执行计划就知道了,如图explainselect*fromanimalwhereid=1oridisnull;其中:ref=ALL:表示全表扫描rows=4:predictivescan4rows(而我们整个表只有4行记录)passed从执行计划可以看出,很有可能会使用or不使用索引,会大大降低查询率,所以一般不建议使用or子句连接条件。那么如何解决呢?其实可以用union代替or,如下:select*fromanimalwhereid=1unionselect*fromanimalwhereidisnull。这个时候你会遍历两次索引,找到所有id=1且所有id=null的行,然后用一个临时表存储最后的结果,最后扫描临时表。三、总结1、定义表时,尽量不要让字段值为null,可以使用default设置默认值。2、尽量用union代替or,避免没有索引的查询。3.注意,如果使用id=null的等价查询,则不会匹配值为null的行,但应该使用id为null。也欢迎大家说说踩过的坑。
