【介绍】mysql
工做的越久越到的的问题越多,就越是以为一些“老话”历久弥新;因为最近的学习计划是深刻的学习一遍MySQL优化器;学习过程当中的一些成果sql
也会发布到这里,一来是为了整理本身已经知道的和新学到的,二来是为了给本身的网站作个友情链接数据库
【is null 优化】学习
若是咱们在定义表的时候就给不能为null的列加上not null 那么就将是一个很是好的实践,想一想若是接下来有查询要查找col is null的话,由于mysql测试
已经知道col不可能为null 因此MySQL会直接把这个优化掉,返回空结果集;理由是根本不会存在col is null的行优化
【看一下is null 有多吊吧】网站
第一步:创建一个测试表spa
create table t(id int not null auto_increment primary key, x int not null,y int); create index idx_t_x on t(x); -- x 是not null 的 create index idx_t_y on t(y); -- y 是能够为空的 insert into t(x,y) values(1,null),(2,2),(3,3);
第二步:观察MySQL针对null 和 not null的列的处理是有本质区别的code
explain select x from t where x is null; +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------+ | 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | Impossible WHERE | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------+ 1 row in set, 1 warning (0.00 sec)
因为x 不可能为空,因此当查询条件是x is null的状况下MySQL不用去查就直接返回了空结果集,正确+省事blog
mysql> explain select x from t where y is null; +----+-------------+-------+------------+------+---------------+---------+---------+-------+------+----------+-----------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+---------+---------+-------+------+----------+-----------------------+ | 1 | SIMPLE | t | NULL | ref | idx_t_y | idx_t_y | 5 | const | 1 | 100.00 | Using index condition | +----+-------------+-------+------------+------+---------------+---------+---------+-------+------+----------+-----------------------+ 1 row in set, 1 warning (0.00 sec)
因为y是能够为null的、因此表的访问过程就变成了先读索引再回表(ref),就算y中的每一行都有值,其过程仍是要比上面的x is null的查询要多作很多
第三步:无论列上有没有索引只要表定义中指定了条件不为null那么针对is null查询仍是能够获得优化
alter table t add column z int; explain select x from t where z is null; +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+ | 1 | SIMPLE | t | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 33.33 | Using where | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+ 1 row in set, 1 warning (0.00 sec)
因为z上没有索引也没有定义成 not null 因此针对 z is null只能直接全表扫描、下面看一下定义了not null的状况
alter table t drop column z; alter table t add column z int not null; -- 在这种没有指定默认值的状况下、int类型默认为0 explain select * from t where z is null; +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------+ | 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | Impossible WHERE | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------+ 1 row in set, 1 warning (0.00 sec)
【总结】
not null 应该算是关系模板中域完整性的一部分吧,这个已是关系型数据库中的一部分;在定义表的时候就应该尽量的把完整性加进去,这样优化
器获得的信息更多,作出的选择也更加机智。
【个人个站点】
---