【黄啊码】MySQL中NULL和““的区别以及对索引的影响
定义和区别
-
定义:
-
空值(NULL)的长度是NULL,不确定占用了多少存储空间,但是占用存储空间的
-
空字符串(’’)的长度是0,是不占用空间的
-
区别:
-
在进行count()统计某列时候,如果用null值系统会自动忽略掉,但是空字符会进行统计。
-
不过count(*)会被优化,直接返回总行数,包括null值。
-
判断null用is null或is not null,SQL可以使用ifnull()函数进行处理;
-
判断空字符用=''或者!=''进行处理。
-
对于timestamp数据类型,插入null值会是当前系统时间;
-
插入空字符,则出现0000-00-00 00:00:00
实例:
-
CREATE TABLE test_ab (id int,
-
col_a varchar(128),
-
col_b varchar(128) not null
-
);
-
-
insert test_ab(id,col_a,col_b) values(1,1,1);
-
insert test_ab(id,col_a,col_b) values(2,'','');
-
insert test_ab(id,col_a,col_b) values(3,null,'');
-
insert test_ab(id,col_a,col_b) values(4,null,1);
-
-
mysql> select * from test_ab;
-
+------+-------+-------+
-
| id | col_a | col_b |
-
+------+-------+-------+
-
| 1 | 1 | 1 |
-
| 2 | | |
-
| 3 | NULL | |
-
| 4 | NULL | 1 |
-
+------+-------+-------+
-
4 rows in set (0.00 sec)
- 首先比较一下,空字符(’’)和空值(null)查询方式的不同:
-
mysql> select * from test_ab where col_a = '';
-
+------+-------+-------+
-
| id | col_a | col_b |
-
+------+-------+-------+
-
| 2 | | |
-
+------+-------+-------+
-
1 row in set (0.00 sec)
-
-
mysql> select * from test_ab where col_a is null;
-
+------+-------+-------+
-
| id | col_a | col_b |
-
+------+-------+-------+
-
| 3 | NULL | |
-
| 4 | NULL | 1 |
-
+------+-------+-------+
-
2 rows in set (0.00 sec)
由此可见,null
和''
的查询方式不同。而且比较字符 ‘=’’>’ ‘<’ ‘<>’不能用于查询null,
如果需要查询空值(null),需使用is null 和is not null。
- 第二种比较,参与运算
-
mysql> select col_a+1 from test_ab where id = 4;
-
+---------+
-
| col_a+1 |
-
+---------+
-
| NULL |
-
+---------+
-
1 row in set (0.00 sec)
-
-
mysql> select col_b+1 from test_ab where id = 4;
-
+---------+
-
| col_b+1 |
-
+---------+
-
| 2 |
-
+---------+
-
1 row in set (0.00 sec)
由此可见,空值(null)不能参与任何计算,因为空值参与任何计算都为空。
所以,当程序业务中存在计算的时候,需要特别注意。
如果非要参与计算,需使用ifnull函数,将null转换为''
才能正常计算。
- 第三种比较,统计数量
-
mysql> select count(col_a) from test_ab;
-
+--------------+
-
| count(col_a) |
-
+--------------+
-
| 2 |
-
+--------------+
-
1 row in set (0.00 sec)
-
-
mysql> select count(col_b) from test_ab;
-
+--------------+
-
| count(col_b) |
-
+--------------+
-
| 4 |
-
+--------------+
-
1 row in set (0.00 sec)
由此可见,当统计数量的时候。空值(null)并不会被当成有效值去统计。同理,sum()求和的时候,null也不会被统计进来,这样就能理解,为什么null计算的时候结果为空,而sum()求和的时候结果正常了。
为什么Mysql 数据库尽量避免NULL?
(1)如果查询中包含可为NULL的列,对Mysql来说更难优化,因为可为NULL的列使得索引,索引统计和值比较都更复杂。
(2)含NULL复合索引无效.
(3)可为NULL的列会使用更多的存储空间,在Mysql中也需要特殊处理。
(4)当可为NULL的列被索引时,每个索引记录需要一个额外的字节,在MyISAM里甚至还可能导致固定大小的索引(例如只有一个整数列的索引)变成可变大小的索引。
MySQL索引失效的几种清空
1.索引不存储null值
更准确的说,单列索引不存储null值,复合索引不存储全为null的值。索引不能存储Null,所以对这列采用is null条件时,因为索引上根本
没Null值,不能利用到索引,只能全表扫描。
为什么索引列不能存Null值?
将索引列值进行建树,其中必然涉及到诸多的比较操作。Null值的特殊性就在于参与的运算大多取值为null。
这样的话,null值实际上是不能参与进建索引的过程。也就是说,null值不会像其他取值一样出现在索引树的叶子节点上。
2.不适合键值较少的列(重复数据较多的列)
假如索引列TYPE有5个键值,如果有1万条数据,那么 WHERE TYPE = 1将访问表中的2000个数据块。
再加上访问索引块,一共要访问大于200个的数据块。
如果全表扫描,假设10条数据一个数据块,那么只需访问1000个数据块,既然全表扫描访问的数据块
少一些,肯定就不会利用索引了。
3.前导模糊查询不能利用索引(like '%XX'或者like '%XX%')
假如有这样一列code的值为'AAA','AAB','BAA','BAB' ,如果where code like '%AB'条件,由于前面是
模糊的,所以不能利用索引的顺序,必须一个个去找,看是否满足条件。这样会导致全索引扫描或者全表扫
描。如果是这样的条件where code like 'A % ',就可以查找CODE中A开头的CODE的位置,当碰到B开头的
数据时,就可以停止查找了,因为后面的数据一定不满足要求。这样就可以利用索引了。
4.索引失效的几种情况
1.如果条件中有or,即使其中有条件带索引也不会使用(这也是为什么尽量少用or的原因)
要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引
2.对于多列索引,不是使用的第一部分,则不会使用索引
3.like查询以%开头
4.如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引
5.如果mysql估计使用全表扫描要比使用索引快,则不使用索引
5.MySQL主要提供2种方式的索引:B-Tree索引,Hash索引
B树索引具有范围查找和前缀查找的能力,对于有N节点的B树,检索一条记录的复杂度为O(LogN)。相当于二分查找。
哈希索引只能做等于查找,但是无论多大的Hash表,查找复杂度都是O(1)。
显然,如果值的差异性大,并且以等值查找(=、 、in)为主,Hash索引是更高效的选择,它有O(1)的查找复杂度。
如果值的差异性相对较差,并且以范围查找为主,B树是更好的选择,它支持范围查找。
文章来源: markwcm.blog.csdn.net,作者:黄啊码,版权归原作者所有,如需转载,请联系作者。
原文链接:markwcm.blog.csdn.net/article/details/123710942
- 点赞
- 收藏
- 关注作者
评论(0)