原文: https://cloud.tencent.com/developer/article/1465618

本次来讲解与 SQL 查询有关的两个小知识点,掌握这些知识点,能够让你避免踩坑以及提高查询效率。

1、允许字段的值为 null,往往会引发灾难

首先,先准备点数据,后面好演示

create table animal(
id int,
name char(20),
index(id)
)engine=innodb;

index(id) 表示给 id 这个字段创建索引,并且 id 和 name 都允许为 null。

接着插入4条数据,其中最后一条数据的 id  为。

insert into animal(id, name) values(1, '猫');
insert into animal(id, name) values(2, '狗');
insert into animal(id, name) values(3, '猪');
insert into animal(id, name) values(null, '无名动物');

注意:代码块可以左右拉动

此时表中的数据为

这时我们查询表中 id  != 1 的动物有哪些

select * from animal where id != 1;

结果如下:

此时我们只找到了两行数据,按道理应该是三行的,但是 id = null 的这一行居然没有被匹配到,,可能大家听说过,null 与任何 其他值都不相等,按道理 null != 1 是成立的话,然而现实很残酷,它就是不会被匹配到。

所以,坚决不允许字段的值为 null,否则可能会出现与预期不符合的结果。

反正我之前有踩过这个坑,不知道大家踩过木有?

但是万一有人设置了允许为 null 值怎么办?如果真的这样的话,对于 != 的查找,后面可以多加一个 or id is null 的子句(注意,是 is null,不是 = null,因为 id = null 也不会匹配到值为 null 的行)。即

select * from animal where id != 1 or id is null;

结果如下:

2、尽可能用 union 来代替 or

(1)、刚才我们给 id 这个字段建立了索引,如果我们来进行等值操作的话,一般会走索引操作,不信你看:

explain select * from animal where id = 1;

结果如下:

通过执行计划可以看见,id 上的等值查找能够走索引查询(估计在你的意料之中),其中

type = ref :表示走非唯一索引 rows = 1 :预测扫描一行

(2)、那 id is null 会走索引吗?答是会的,如图

explain select * from animal where id is null;

其中

type = ref :表示走非唯一索引 rows = 1 :预测扫描一行

(3)、那么问题来了,那如果我们要找出 id = 1 或者 id = null 的动物,我们可能会用 or 语句来连接,即

select * from animal where id = 1 or id is null;

那么这条语句会走索引吗?

有没有走索引,看执行计划就知道了,如图

explain select * from animal where id = 1 or id is null;

其中:

ref = ALL:表示全表扫描

rows = 4 :预测扫描4行(而我们整个表就只有4行记录)

通过执行计划可以看出,使用 or 是很有可能不走索引的,这将会大大降低查询的速率,所以一般不建议使用 or 子句来连接条件。

那么该如何解决?

其实可以用 union 来取代 or,即如下:

select * from animal where id = 1 union select * from animal where id is null.

此时就会分别走两次索引,找出所有 id = 1 和 所有 id = null  的行,然后再用一个临时表来存放最终的结果,最后再扫描临时表。

3、总结

1、定义表的时候,尽量不允许字段值为 null,可以用 default 设置默认值。

2、尽量用 union 来代替 or,避免查询没有走索引。

3、注意,用 id = null 的等值查询,也是不会匹配到值为 null 的行的,而是应该用 id is null。

也欢迎大家说一说自己踩过的坑

这两个小技巧,让我的SQL语句不仅躲了坑,还提升了1000 倍的更多相关文章

  1. Objective-C中3种枚举比较及KVC两个小技巧

    Objective-C中3种枚举比较及KVO两个小技巧 一:oc的3种枚举 for循环 for in 枚举块 如代码 NSUInteger totalCount = 10000; NSMutableA ...

  2. Linux命令学习之两个小技巧(1)

    本篇主要想讲两个小技巧.本来技巧之类的话应该放在学完整个东西之后或者在学习中遇到时再说的,但是这两个技巧其实很简单,很多人只要我一提就知道了.与其说是技巧,不如说是注意事项. 自动补全 在Linux终 ...

  3. sql server 小技巧(7) 导出完整sql server 数据库成一个sql文件,包含表结构及数据

    1. 右健数据库 –> Tasks –> Generate Scripts   2. 选择所有的表   3. 下一步,选择Advanded, Types of data to script ...

  4. 自制小工具大大加速MySQL SQL语句优化(附源码)

    引言 优化SQL,是DBA常见的工作之一.如何高效.快速地优化一条语句,是每个DBA经常要面对的一个问题.在日常的优化工作中,我发现有很多操作是在优化过程中必不可少的步骤.然而这些步骤重复性的执行,又 ...

  5. C# GDI+ 处理文本的两个小技巧

    private void button7_Click(object sender, EventArgs e) { Graphics g = this.CreateGraphics(); g.FillR ...

  6. js两个小技巧【看到了就记录一下】

    1.不声明第三个变量实现交换 ,b=; a=[b,b=a][];//执行完这句代码之后 a的值为2 b的值为1了 2.&&和||的用法 (学会了立马感觉高大尚了吧) ; //传统if语 ...

  7. Redis的两个小技巧

    1.通配删除相同前缀的缓存 DEL命令的参数不支持通配符,但我们可以结合Linux的管道和xargs命令自己实现删除所有符合规则的键. 比如要删除所有以“structure_”开头的键,就可以执行下面 ...

  8. 小记NodeJS两项小技巧(与HTTP相关)

    1,兼容HTTP1.1和HTTP1.0 区别在content-length,1.0接受定长,不接受变长,导致transfer-encodeing的chunked模式无法识别,最终导致无法识别BODY. ...

  9. .Net开发的两个小技巧

    一.@符号的妙用 1.可以作为保留关键字的标识符 C#规范当中,不允许使用保留关键字(class.bool等)当作普通的标识符来命名,这时候@符号作用就体现 出来了,可以通过@符号前缀把这些保留关键字 ...

随机推荐

  1. VS操作中遇到的问题及解决

    1.无法解析的外部符号 _main,该符号在函数 "int __cdecl invoke_main(void)" (?invoke_main@@YAHXZ) 中被引用 2. /ZI ...

  2. bootstrap ui样例

    http://demo.codedefault.com/demo/ui/theadmin/samples/invoicer/settings.html

  3. input 关键字提示,对于一些特定优化来说,很有用处

    只用html就可以做出提醒操作:效果如下图 这里是代码,怎么样,很简单吧 <form action="/server" method="post"> ...

  4. mysql之字段的修改,添加、删除,多表关系(外键),单表详细操作(增删改)

    字段的修改.添加和删除 create table tf1( id int primary key auto_increment, x int, y int ); #修改 alter table tf1 ...

  5. Iptables不适用与socks协议吗?

    需求描述   现有一个台多公网IP服务器,用作于内网网关,通过NAT访问公网使用,要求不同的内网地址访问公网时使用不同的公网IP.可以简单理解为内网与公网IP进行一对一访问外网的映射. 服务器名称 I ...

  6. 2017-2018 ACM-ICPC Southeastern European Regional Programming Contest (SEERC 2017)

    2017-2018 ACM-ICPC Southeastern European Regional Programming Contest (SEERC 2017) 全靠 wxh的博客 补完这套.wx ...

  7. React / Ant Design Pro 实现Canvas画布实时自适应

    如何实现canvas根据父容器进行自适应? Ant Design的组件都提供了强大的自适应能力,为了对齐父组件,镶嵌在Ant Design组件里的canvas也需要能根据父级容器进行自适应的能力,页面 ...

  8. MySQL版本问题导致的SQLException

    背景 ​ 学习使用 SpringCloud 时,使用 消费者 调用 生产者 时抛出 SQLException,持久层框架为 MyBatis,数据库为最新版本的 MySQL 版本如下: Server v ...

  9. Layui 隐藏左侧菜单

    简单实现 //隐藏菜单 var bl = $("#LAY_app_flexible").hasClass("layui-icon-shrink-right"); ...

  10. 【luoguP1533】可怜的狗狗

    题目链接 发现区间按左端点排序后右端点也是单调的,所以扫一遍就行了,用权值线段树维护第\(k\)大 #include<algorithm> #include<iostream> ...