要尽可能地把字段定义为 NOT NULL,即使应用程序无须保存 NULL(没有值),也有许多表包含了可空列(Nullable Column)
这仅仅是因为它为默认选项。除非真的要保存 NULL,否则就把列定义为 NOT NULL

MySQL难以优化引用了可空列的查询,它会使索引、索引统计和值更加复杂。
可空列需要更多的储存空间,还需要在MySQL内部进行特殊处理。当可空列被索引的时候,
每条记录都需要一个额外的字节,还可能导致 MyISAM 中固定大小的索引(例如一个整数列上的索引)变成可变大小的索引。
即使要在表中储存「没有值」的字段,还是有可能不使用 NULL 的,考虑使用 0、特殊值或空字符串来代替它。
把 NULL 列改为 NOT NULL 带来的性能提升很小,所以除非确定它引入了问题,否则就不要把它当作优先的优化措施。
然后,如果计划对列进行索引,就要尽量避免把它设置为可空,虽然在mysql里 Null值的列也是走索引的

 mysql> SELECT 1 IS NULL, 1 IS NOT NULL;
+-----------+---------------+
| 1 IS NULL | 1 IS NOT NULL |
+-----------+---------------+
| 0 | 1 |
+-----------+---------------+
1 row in set mysql> SELECT 0 IS NULL, 0 IS NOT NULL, '' IS NULL, '' IS NOT NULL;
+-----------+---------------+------------+----------------+
| 0 IS NULL | 0 IS NOT NULL | '' IS NULL | '' IS NOT NULL |
+-----------+---------------+------------+----------------+
| 0 | 1 | 0 | 1 |
+-----------+---------------+------------+----------------+

测试

CREATE TABLE `test_null` (
`id` int(11) DEFAULT NULL,
`mark` varchar(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8; create procedure test_null(in num int)
BEGIN
DECLARE i int;
set i=1;
while (i<num)
DO
if mod(i,10)!=0 then
insert into test_null values (i,concat('aaa',i));
else
insert into test_null values (null,concat('aaa',i));
end if;
set i=i+1;
END while;
END; call test_null(10000);
mysql> select count(*) from test_null;
+----------+
| count(*) |
+----------+
| 9999 |
+----------+
没加任何索引时
mysql> explain SELECT * from test_null WHERE id is null;
+----+-------------+-----------+------------+------+---------------+------+---------+------+-------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-----------+------------+------+---------------+------+---------+------+-------+----------+-------------+
| 1 | SIMPLE | test_null | NULL | ALL | NULL | NULL | NULL | NULL | 10105 | 10 | Using where |
+----+-------------+-----------+------------+------+---------------+------+---------+------+-------+----------+-------------+
在id上加普通索引
create index idx_test_null on test_null(id);
mysql> explain SELECT * from test_null WHERE id is null;
+----+-------------+-----------+------------+------+---------------+---------------+---------+-------+------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-----------+------------+------+---------------+---------------+---------+-------+------+----------+-----------------------+
| 1 | SIMPLE | test_null | NULL | ref | idx_test_null | idx_test_null | 5 | const | 999 | 100 | Using index condition |
+----+-------------+-----------+------------+------+---------------+---------------+---------+-------+------+----------+-----------------------+
null值也是走索引的

 null在count统计时时的问题

create table test (id int,val int);
INSERT INTO `test` VALUES ('', '');
INSERT INTO `test` VALUES ('', '');
INSERT INTO `test` VALUES ('', '');
INSERT INTO `test` VALUES ('', '');
INSERT INTO `test` VALUES ('', '');

1条语句统计id=1,id=2的个数

一般错误写法

select count(id=1) ,count(id=2) from test;

mysql> select count(id=1) ,count(id=2) from test;
+-------------+-------------+
| count(id=1) | count(id=2) |
+-------------+-------------+
| 5 | 5 |
+-------------+-------------+

需要注意count只不会统计null的列,0的会统计

mysql> select 1 or null as or1,1 and null as and1 ,0 and null as and0 ,0 or null as null0;
+------+------+------+-------+
| or1 | and1 | and0 | null0 |
+------+------+------+-------+
| 1 | NULL | 0 | NULL |
+------+------+------+-------+
mysql> select id=1 ,id=2 from test;
+------+------+
| id=1 | id=2 |
+------+------+
| 1 | 0 |
| 1 | 0 |
| 0 | 1 |
| 0 | 1 |
| 0 | 1 |
+------+------+

要把0值变为null,count时不计算即可

mysql> select count(id=1) ,count(id=2) from test;
+-------------+-------------+
| count(id=1) | count(id=2) |
+-------------+-------------+
| 5 | 5 |
+-------------+-------------+
mysql> select id=1 or null,id=2 or null from test;
+--------------+--------------+
| id=1 or null | id=2 or null |
+--------------+--------------+
| 1 | NULL |
| 1 | NULL |
| NULL | 1 |
| NULL | 1 |
| NULL | 1 |
+--------------+--------------+

所以正确的写法是

mysql> select count(id=1 or null),count(id=2 or null) from test;
+---------------------+---------------------+
| count(id=1 or null) | count(id=2 or null) |
+---------------------+---------------------+
| 2 | 3 |
+---------------------+---------------------+
1 row in set (0.00 sec)

select id,count(id) from test where id in(1,2) GROUP BY id

常数与null的运算

DROP TABLE IF EXISTS `test1`;
CREATE TABLE `test1` (
`id` int(11) DEFAULT NULL,
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1; -- ----------------------------
-- Records of test1
-- ----------------------------
INSERT INTO `test1` VALUES ('', '', '');
INSERT INTO `test1` VALUES ('', '', null);
INSERT INTO `test1` VALUES ('', '', '');
INSERT INTO `test1` VALUES ('', '', null);
INSERT INTO `test1` VALUES ('', null, null);

查询 id,a-b的数量(剩余计算)

错误写法

mysql> SELECT id ,(a-b) as remain from test1;
+------+--------+
| id | remain |
+------+--------+
| 1 | 4 |
| 2 | NULL |
| 3 | 2 |
| 4 | NULL |
| 5 | NULL |
+------+--------+

正确写法

mysql> SELECT id ,(IFNULL(a,0)-IFNULL(b,0)) as remain  from test1;
+------+--------+
| id | remain |
+------+--------+
| 1 | 4 |
| 2 | 6 |
| 3 | 2 |
| 4 | 7 |
| 5 | 0 |
+------+--------+

mysql 索引列为Null的走不走索引及null在统计时的问题的更多相关文章

  1. 不要再问我 in,exists 走不走索引了

    微信搜『烟雨星空』,获取最新好文. 前言 最近,有一个业务需求,给我一份数据 A ,把它在数据库 B 中存在,而又比 A 多出的部分算出来.由于数据比较杂乱,我这里简化模型. 然后就会发现,我去,这不 ...

  2. mysql 索引 大于等于 走不走索引 最左前缀

    你可以认为联合索引是闯关游戏的设计 例如你这个联合索引是state/city/zipCode 那么state就是第一关 city是第二关, zipCode就是第三关 你必须匹配了第一关,才能匹配第二关 ...

  3. mysql 索引优化,索引建立原则和不走索引的原因

    第一:选择唯一性索引 唯一性索引的值是唯一的,可以更快捷的通过该索引来确定某条记录. 2.索引的列为where 后面经常作为条件的字段建立索引 如果某个字段经常作为查询条件,而且又有较少的重复列或者是 ...

  4. SQL语句优化、mysql不走索引的原因、数据库索引的设计原则

    SQL语句优化 1 企业SQL优化思路 1.把一个大的不使用索引的SQL语句按照功能进行拆分 2.长的SQL语句无法使用索引,能不能变成2条短的SQL语句让它分别使用上索引. 3.对SQL语句功能的拆 ...

  5. MySQL全面瓦解24:构建高性能索引(策略篇)

    学习如果构建高性能的索引之前,我们先来了解下之前的知识,以下两篇是基础原理,了解之后,对面后续索引构建的原则和优化方法会有更清晰的理解: MySQL全面瓦解22:索引的介绍和原理分析 MySQL全面瓦 ...

  6. SQL SERVER 中is null 和 is not null 将会导致索引失效吗?

    其实本来这个问题没有什么好说的,今天优化的时候遇到一个SQL语句,因为比较有意思,所以我截取.简化了SQL语句,演示给大家看,如下所示 declare @bamboo_Code varchar(3); ...

  7. Select * 一定不走索引是否正确?

    Select * 一定不走索引是否正确? 走索引指的是:SQL语句的执行计划用到了1.聚集索引查找  2.索引查找  ,并且查询语句中需要有where子句 根据where子句的过滤条件,去聚集索引或非 ...

  8. oracle查询不走索引的一些情况(索引失效)

    Oracle建立索引的目的是为了避免全表扫描,提高查询的效率. 但是有些情况下发现即使建立了索引,但是写出来的查询还是很慢,然后会发现是索引失效导致的,所以需要了解一下那些情况会导致索引失效,即查询不 ...

  9. mysql中走与不走索引的情况汇集(待全量实验)

    说明 在MySQL中,并不是你建立了索引,并且你在SQL中使用到了该列,MySQL就肯定会使用到那些索引的,有一些情况很可能在你不知不觉中,你就“成功的避开了”MySQL的所有索引. 索引列参与计算 ...

随机推荐

  1. React中路由传参及接收参数的方式

    注意:  路由表改变后要重启服务      方式 一:          通过params         1.路由表中                     <Route path=' /s ...

  2. cmd编译运行java

    新建.java结尾的文件 内容 public class hello{ public static void main(String[] args){ System.out.println(" ...

  3. oracle12c:通过oracle客户端工具配置tns,并使用sqlldr进行批量导入数据

    通过oracle客户端工具配置tns: 进入oracle配置工具“Net Configuration Assistant”-> 点击“下一步”,完成tns配置. 测试是否tns可用 命令:tns ...

  4. 谈谈spring-boot不同包结构下,同样的类名冲突导致服务启动失败解决方案

    项目背景: 某日,有需求要在三天的时间内完成两个大项目的项目合并,因为之前两个项目的包结构和类名都很多相同,于是开始考虑使用加一级包进行隔离,类似于这种结构 但是在启动的过程中,抛出来这样的异常: C ...

  5. hasattr(obj,attr) 判断前面是否有后面的属性

    hasattr(obj,attr) 判断前面是否有后面的属性

  6. 使用vue-cli快速搭建大型单页面应用开发环境

    工作环境:terminal,已经全局安装了vue(可使用npm install -g vue) 全局安装vue-cli npm install -g vue-cli 创建一个基于webpack模板的项 ...

  7. 点击后退按钮回到本页面中的另一个标签页(tab)

    在使用zepto进行微信网页开发的时候,遇到一个情况,在本页面存在四个TAB栏,每点击一个栏会显示相应的内容,下图这种: 现在有一个需求是,用户点击了后退按钮,需要回到上一次点击的tab栏. 这个需求 ...

  8. Extensions in UWP Community Toolkit - ListViewExtensions

    概述 UWP Community Toolkit Extensions 中有一个为 ListView 提供的扩展 - ListViewExtensions,本篇我们结合代码详细讲解 ListView  ...

  9. Java面试题2--数据类型

    1. Java的数据类型? 2. Java的封装类型? 3. 基本类型和封装类型的区别? 基本类型只能按值传递,而对应的封装类是按引用传递的. 基本类型是在堆栈上创建的,而所有的对象类型都是在堆上创建 ...

  10. 1.UTF8字符集csv文件在oracle下乱码问题处理

    1.问题描述 在excel中生成了一个UTF-8编码格式的csv文件准备导入数据库,在notpad++下打开显示正常,编码集为UTF-8,通过pl/sql dev导入oracle是出现乱码,此时初步推 ...