【黄啊码】MySQL中NULL和““的区别以及对索引的影响

举报
黄啊码 发表于 2022/06/28 23:16:45 2022/06/28
2.2k+ 0 0
【摘要】 定义和区别 定义:空值(NULL)的长度是NULL,不确定占用了多少存储空间,但是占用存储空间的空字符串(’’)的长度是0,是不占用空间的区别:在进行count()统计某列时候,如果用null值系统会自动忽略掉,但是空字符会进行统计。不过count(*)会被优化,直接返回总行数,包括null值。判断null用is null或is no...

定义和区别


      定义:
      空值(NULL)的长度是NULL,不确定占用了多少存储空间,但是占用存储空间的
      空字符串(’’)的长度是0,是不占用空间的
      区别:
      在进行count()统计某列时候,如果用null值系统会自动忽略掉,但是空字符会进行统计。
      不过count(*)会被优化,直接返回总行数,包括null值。
      判断nullis nullis not nullSQL可以使用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

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

作者其他文章

评论(0

抱歉,系统识别当前为高风险访问,暂不支持该操作

    全部回复

    上滑加载中

    设置昵称

    在此一键设置昵称,即可参与社区互动!

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。