【介紹】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 應該算是關係模板中域完整性的一部分吧,這個已是關係型數據庫中的一部分;在定義表的時候就應該儘量的把完整性加進去,這樣優化
器獲得的信息更多,作出的選擇也更加機智。
【個人個站點】
---