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的所有索引. 索引列参与计算 ...
随机推荐
- SpringCloud的应用发布(一)SpringCloud的样例工程
前言 这个综合例子创建了 6个微服务应用 一个服务注册中心 SvcReg(EurekaServer),生产中要考虑高可用 一个配置中心 CfgMgr + git目录存储配置(ConfigServer, ...
- java中的引用类型的对象存放在哪里
根据上下文来确定.比如void func(){ Object obj = new Object();//这个obj在函数的栈里.}class Test{ private Object obj ...
- Lua编写wireshark插件初探——解析Websocket上的MQTT协议
一.背景 最近在做物联网流量分析时发现, App在使用MQTT协议时往往通过SSL+WebSocket+MQTT这种方式与服务器通信,在使用SSL中间人截获数据后,Wireshark不能自动解析出MQ ...
- Commons-FileUpload组件的应用
<% request.setCharacterEncoding("utf-8"); String uploadFileName="";//上传的文 ...
- zoj 3950 how many nines
https://vjudge.net/problem/ZOJ-3950 题意: 给出两个日期,计算从第一个日期开始到第二个日期,每一天的日期中的9加起来一共有多少个. 思路: 看题解补的题.首先看这题 ...
- TreeMap就这么简单【源码剖析】
前言 声明,本文用得是jdk1.8 前面章节回顾: Collection总览 List集合就这么简单[源码剖析] Map集合.散列表.红黑树介绍 HashMap就是这么简单[源码剖析] LinkedH ...
- 如何从二维数组中的多个key中获取指定key的值?
精华 LOVEME96 2016-10-21 10:40:19 浏览(1512) 回答(3) 赞(0) 新手求教:二维数组中一般会有多个key,如果我们要获得指定key的值,应该怎么做? 问题标签: ...
- .Net Core小技巧 - 使用Swagger上传文件
前言 随着前后端分离开发模式的普及,后端人员更多是编写服务端API接口.调用接口实现文件上传是一个常见的功能,同时也需要一个选择文件上传的界面,可以编写前端界面上传,可以使用Postman.curl来 ...
- [JLOI2015]管道连接
题目描述 小铭铭最近进入了某情报部门,该部门正在被如何建立安全的通道连接困扰.该部门有 n 个情报站,用 1 到 n 的整数编号.给出 m 对情报站 ui;vi 和费用 wi,表示情报站 ui 和 v ...
- 洛谷mNOIP模拟赛Day2-星空
题目背景 pdf题面和大样例链接:http://pan.baidu.com/s/1cawM7c 密码:xgxv 命运偷走如果只留下结果, 时间偷走初衷只留下了苦衷. 你来过,然后你走后,只留下星空. ...