爲什麼表設計時必須把字段定義爲NOT NULL並設默認值

空間佔用的坑

空’'在存儲過程中是不會佔用空間的,但是NULL會。就像一個杯子,空表示杯子是真空的,NULL表示裝的空氣。

mysql> SELECT length('1'),length(NULL),length('');

+-------------+--------------+------------+
| length('1') | length(NULL) | length('') |
+-------------+--------------+------------+
|           1 | NULL         |          0 |
+-------------+--------------+------------+
1 row in set

mysql> 

查詢的坑

如果要查詢表的NULL需要使用 is nullis not null,如果直接使用=/!=/in/not inl將查詢不到值

mysql> SELECT * FROM `user`;
+----+------+-----+---------+
| id | name | age | address |
+----+------+-----+---------+
|  1 | wyf  |  32 | 合肥    |
|  2 | xx   |  31 | 北京    |
|  3 | yy   |  30 | 上海    |
|  4 | zz   |  11 |         |
|  5 | aa   |  21 | NULL    |
+----+------+-----+---------+
5 rows in set

mysql> SELECT * FROM `user` WHERE address IS NULL;
+----+------+-----+---------+
| id | name | age | address |
+----+------+-----+---------+
|  5 | aa   |  21 | NULL    |
+----+------+-----+---------+
1 row in set

mysql> SELECT * FROM `user` WHERE address = NULL;
Empty set

mysql> 

NULL統計的坑

如果使用count()等統計函數,將不會統計NULL。如下,一共有5條數據,統計address就只返回4。

mysql> SELECT * FROM `user`;
+----+------+-----+---------+
| id | name | age | address |
+----+------+-----+---------+
|  1 | wyf  |  32 | 合肥    |
|  2 | xx   |  31 | 北京    |
|  3 | yy   |  30 | 上海    |
|  4 | zz   |  11 |         |
|  5 | aa   |  21 | NULL    |
+----+------+-----+---------+
5 rows in set

mysql> SELECT COUNT(address) FROM `user`;
+----------------+
| COUNT(address) |
+----------------+
|              4 |
+----------------+
1 row in set

mysql> 

索引的坑

Mysql的索引會爲NULL值做特殊處理,導致整個索引的查詢效率下降。如果是語句中有 is null會使用索引,如果語句中有is not null則會導致索引失效,如下:

查看索引:


mysql> show index from user;
+-------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name    | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| user  |          0 | PRIMARY     |            1 | id          | A         |           5 | NULL     | NULL   |      | BTREE      |         |               |
| user  |          1 | idx_name    |            1 | name        | A         |           5 | NULL     | NULL   | YES  | BTREE      |         |               |
| user  |          1 | idx_address |            1 | address     | A         |           5 | NULL     | NULL   | YES  | BTREE      |         |               |
+-------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
3 rows in set

is null 會使用索引

mysql> explain select * from user where address is null;
+----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys | key         | key_len | ref   | rows | filtered | Extra                 |
+----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+----------+-----------------------+
|  1 | SIMPLE      | user  | NULL       | ref  | idx_address   | idx_address | 1023    | const |    1 |      100 | Using index condition |
+----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+----------+-----------------------+
1 row in set

is not null 不會使用索引

mysql> explain select * from user where address is not null;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | user  | NULL       | ALL  | idx_address   | NULL | NULL    | NULL |    5 |       80 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set

mysql> 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章