mysql 索引列为Null的走不走索引及null在统计时的问题
要尽可能地把字段定义为 NOT NULL,即使应用程序无须保存 NULL(没有值),也有许多表包含了可空列(Nullable Column)
这仅仅是因为它为默认选项。除非真的要保存 NULL,否则就把列定义为 NOT NULLMySQL难以优化引用了可空列的查询,它会使索引、索引统计和值更加复杂。
可空列需要更多的储存空间,还需要在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在统计时的问题的更多相关文章
- 不要再问我 in,exists 走不走索引了
微信搜『烟雨星空』,获取最新好文. 前言 最近,有一个业务需求,给我一份数据 A ,把它在数据库 B 中存在,而又比 A 多出的部分算出来.由于数据比较杂乱,我这里简化模型. 然后就会发现,我去,这不 ...
- mysql 索引 大于等于 走不走索引 最左前缀
你可以认为联合索引是闯关游戏的设计 例如你这个联合索引是state/city/zipCode 那么state就是第一关 city是第二关, zipCode就是第三关 你必须匹配了第一关,才能匹配第二关 ...
- mysql 索引优化,索引建立原则和不走索引的原因
第一:选择唯一性索引 唯一性索引的值是唯一的,可以更快捷的通过该索引来确定某条记录. 2.索引的列为where 后面经常作为条件的字段建立索引 如果某个字段经常作为查询条件,而且又有较少的重复列或者是 ...
- SQL语句优化、mysql不走索引的原因、数据库索引的设计原则
SQL语句优化 1 企业SQL优化思路 1.把一个大的不使用索引的SQL语句按照功能进行拆分 2.长的SQL语句无法使用索引,能不能变成2条短的SQL语句让它分别使用上索引. 3.对SQL语句功能的拆 ...
- MySQL全面瓦解24:构建高性能索引(策略篇)
学习如果构建高性能的索引之前,我们先来了解下之前的知识,以下两篇是基础原理,了解之后,对面后续索引构建的原则和优化方法会有更清晰的理解: MySQL全面瓦解22:索引的介绍和原理分析 MySQL全面瓦 ...
- SQL SERVER 中is null 和 is not null 将会导致索引失效吗?
其实本来这个问题没有什么好说的,今天优化的时候遇到一个SQL语句,因为比较有意思,所以我截取.简化了SQL语句,演示给大家看,如下所示 declare @bamboo_Code varchar(3); ...
- Select * 一定不走索引是否正确?
Select * 一定不走索引是否正确? 走索引指的是:SQL语句的执行计划用到了1.聚集索引查找 2.索引查找 ,并且查询语句中需要有where子句 根据where子句的过滤条件,去聚集索引或非 ...
- oracle查询不走索引的一些情况(索引失效)
Oracle建立索引的目的是为了避免全表扫描,提高查询的效率. 但是有些情况下发现即使建立了索引,但是写出来的查询还是很慢,然后会发现是索引失效导致的,所以需要了解一下那些情况会导致索引失效,即查询不 ...
- mysql中走与不走索引的情况汇集(待全量实验)
说明 在MySQL中,并不是你建立了索引,并且你在SQL中使用到了该列,MySQL就肯定会使用到那些索引的,有一些情况很可能在你不知不觉中,你就“成功的避开了”MySQL的所有索引. 索引列参与计算 ...
随机推荐
- 阿里云API网关(8)开发指南-SDK下载
网关指南: https://help.aliyun.com/document_detail/29487.html?spm=5176.doc48835.6.550.23Oqbl 网关控制台: https ...
- 阿里云API网关(3)快速入门(调用 API)
网关指南: https://help.aliyun.com/document_detail/29487.html?spm=5176.doc48835.6.550.23Oqbl 网关控制台: https ...
- 新概念英语(1-41)Penny's bag
新概念英语(1-41)Penny's bag Who is the tin of tobacco for? A:Is that bag heavy, Penny? B:Not very. A:Here ...
- Let's Encrypt,免费好用的 HTTPS 证书
很早之前我就在关注 Let's Encrypt 这个免费.自动化.开放的证书签发服务.它由 ISRG(Internet Security Research Group,互联网安全研究小组)提供服务,而 ...
- Python之进程
进程 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.在早期面向进程设计的计算机结构中,进程是程序的基本执行实体:在当代 ...
- python 保障系统(一)
python 保障系统 from django.shortcuts import render,redirect,HttpResponse from app01 import models from ...
- Git篇(基础)
安装过程省略... 至于安装目录的有关功能,略过... 一.关于初次使用的关键配置命令: 1.配置基本信息,该信息将保存在该用户目录下的.gitconfig文件内 配置用户信息$ git config ...
- JAVA_将唐诗按照古文样式输出
1. 如有唐诗: 锄禾日当午 汗滴禾下土 谁知盘中餐 粒粒皆辛苦 要求将这首唐诗按照古文样式输出,输出格式如下: 粒谁汗锄 粒知滴禾 皆盘禾日 辛中下当 苦餐土午 public class Text ...
- 使用 C# (.NET Core) 实现模板方法模式 (Template Method Pattern)
本文的概念内容来自深入浅出设计模式一书. 项目需求 有一家咖啡店, 供应咖啡和茶, 它们的工序如下: 咖啡: 茶: 可以看到咖啡和茶的制作工序是差不多的, 都是有4步, 其中有两步它们两个是一样的, ...
- C#之winform实现文件拖拽功能
将一个文件拖拽到窗体的某个控件时,将该控件的路径显示在该控件上,只要拿到了路径自然可以读取文件中的内容了 将一个控件的属性AllowDrop设置为true,然后添加DragDrop.DragEnter ...