- 浏览: 1078276 次
- 性别:
- 来自: 武汉
文章分类
最新评论
-
flyfeifei66:
list<bean> bean 中有 list&l ...
freemarker中的list -
BelloVersion:
第五种错误Remote host closed connect ...
客户端如何使用httpclient向https服务器发送数据 -
willxue:
看了半天 前面说的是错的?。。。
反向键索引的原理和用途 -
liulanghan110:
quainter 写道麻烦博主,参数为数组时,paramete ...
MYBATIS 的parameter -
quainter:
麻烦博主,参数为数组时,parameterType怎么写啊?
MYBATIS 的parameter
网上有些资料说含有
null
的列不能创建索引,还有资料说因为一般的索引是
b_
树结构,而
b+
树不能存储
null
值,所以
is null
和
is not null
都不能利用
索引。为了证明以上说法,我做了一下测试。
1. 测试含有 null 的列是否能创建索引
先创建测试数据 :
create table
student
(
id
int
primary key not null
,
sid
int
)
注 : 定义主键时系统自动创建索引,如果 DROP 表,关于这个表的所有索引也被删除,也包括系统创建的索引。
create procedure insertDate()
BEGIN
DECLARE v_id int;
set v_id = 0;
while v_id < 100000
DO
insert into student values(v_id,v_id );
set v_id = v_id + 1;
end while;
END
;
-- 插入数据
call insertDate ()
insert into student ( id ) values ( 100001 )
-- 创建索引
CREATE INDEX
STU_SID
ON
STUDENT
(
SID
ASC
)
PCTFREE
10
ALLOW REVERSE SCANS
;
结果: 可以发现在有 null 的列式可以建立索引的。
2. 测试 is null 和 is not null 能否利用索引
a. 空值很少时的情况
测试数据利用上面的数据, 特点是一共 100001 万条记录,只有1条数据的 sid 为 null 。
注意 : 在一个表的数据大量修改后,要运行下面的命令:
RUNSTATS ON TABLE NBADV. STUDENT FOR INDEX NBADV. STU_SID SHRLEVEL REFERENCE
注:NBADV. STUDENT 是 [模式名].[表名] NBADV.STU_SID 是 [模式名].[表名]
如下查询语句 :
SELECT * FROM STUDENT WHERE SID is null
查询计划如下:
由查询计划可以看出,该语句使用了索引。
再看如下语句:
SELECT * FROM STUDENT WHERE SID is not null
查询计划如下:
由查询计划可以看出,该语句没有使用索引。
再看如下语句:
SELECT SID FROM STUDENT WHERE SID is not null
查询计划如下:
由查询计划可以看出,该语句也没有使用了索引。
一般 SQL 语句,比如 SELECT * FROM STUDENT WHERE SID is null 这句,只告诉了数据库要从哪个表里找到怎样的数据。至于数据库怎样找到我们要的数据,是走索引,还是全表扫描,还是索引和扫描混合,都是 DB2 自己决定的事情。就如我们对一个人说,你从上海来北京吧。那么他是坐飞机呢,还是坐火车,或者是坐汽车,我们并没说。他会用一个标准来选择到底怎么走,比如最快的标准,就会选择飞机,比如最便宜的标准,就会选择火车(长途汽车一般比火车贵吧?)。而 DB2 里的优化器的标准就是最快,怎样最快的得到我们想要的结果。怎样最快的得要想要的结果呢,是走索引还是全表扫描, DB2 优化器收集来的统计信息,然后选择最优的方式。
下面来看上面的语句为什么会产生那样的结果:
第一个 SELECT * FROM STUDENT WHERE SID is null , 可以看到它是利用索引了的。可是 B+ 树的索引(关于 B+ 树索引,可以查询一些资料,有时间我会写些东西来分析它)是不存储 null 值的,它为什么还可以利用索引呢?这就提到了上面的优化器路的选择问题。
我们可以看到此表有 100001 数据,其中 sid 列只有一条是 null 值。也就是 sid 列的索引会存储此列的 100000 条记录的信息,只有一条没有存。在选择怎么的时候, DB2 优化器会试着用这样两种方式,第一种是从表中取出每条记录,然后看它的 sid 值是否为空。第二种是,先从索引找到 sid 列所有非空的数据在表中的位置,然后在扫描表时,如碰到这些位置,则不用取出数据判断是否为空,直接跳到下一条记录。可以看到,第一种方式进行了全表扫描(这里所谓的全表扫描,是指找出每条记录的位置,一般所说的全表扫描是指扫描表每条记录的位置并读取出每条记录的数据)和全表读取数据,第二种方式也进行了全表的扫描,但却没进行全表数据的读取,而是利用索引排除了其他数据,只读取了一条数据。所以,这两种方式分别是这样的:
第一种:全表扫描 + 全盘读取数据
第二种:全表扫描 + 索引扫描 + 读取一条数据
那么,这两种方式哪一种更快呢?
由于索引比整个表小很多,很显然,读取索引比读取整个表的数据时间会少很多,所以第二种方式效率更高。正如上面查询计划显示的那样利用索引和全表扫描共同找到记录。
再来分析这个语句 : SELECT * FROM STUDENT WHERE SID is not null 。 DB2 优化器会有两种方式选择。:
第一种:索引扫描 + 读取数据
第二种:全表扫描 + 读取数据
我们平时所说的利用索引会快,主要是利用索引的有序性可以迅速筛选记录,其实扫描表或者扫描整个表,时间是差不多的。既然索引扫描和全表扫描速度差不多,那么第一种方式和第二种方式速度就一样了?其实第二种方式读取数据会快一些,因为读取数据时,第一种是一条一条的读取,而全表读数据时是一次加载一个 block 来读取 , 所以第二种效率会高一些。
综合上面的考虑,优化器会选择第二种方式,也就是全表扫描。
注: 如果要测试不加条件的索引扫描比全表扫描慢,可以运行这个语句:
alter table transaction_log volatile cardinality
DB2 优化器会强制使用索引
b. 空值很多时的情况
-- 插入数据
delete from
student
create procedure
insertDate
()
BEGIN
DECLARE
v_id
int
;
set
v_id
=
0
;
while
v_id
<
100000
DO
if
v_id
<
9
0000
then
insert into
student
(
id
)
values
(
v_id
);
else
insert into
student
values
(
v_id
,
v_id
);
end if
;
set
v_id
=
v_id
+
1
;
end while
;
END
;
call insertDate ()
RUNSTATS ON TABLE NBADV. STUDENT FOR INDEX NBADV.STU_SID SHRLEVEL REFERENCE
测试语句 :
SELECT * FROM STUDENT WHERE SID is null
这里没有使用索引
SELECT * FROM STUDENT WHERE SID is not null
这里没有使用索引
SELECT sid FROM STUDENT WHERE SID is not null
这里使用了索引。
可以看到,三个同样的语句,前后执行计划却不一样。问题就在于前后的表的数据不一样,第一个只有 1 个 null 值,第二个却有一半的是 null 。下面分析这三个语句。
第一个 SELECT * FROM STUDENT WHERE SID is null
同样有两种方式 :
第一种:全表扫描 + 全盘读取数据
第二种:全表扫描 + 索引扫描 + 读取十分之九数据
这里和第一次测试的区别,就是第二种方式读的数据不是一条而是90%了。从而导致这种利用索引的方式比第一种慢,而优化器选择了第一种。
第二个 SELECT * FROM STUDENT WHERE SID is not null
两种方式 :
第一种:索引扫描 + 读取数据(全表的10%)
第二种:全表扫描 + 读取数据(全表)
由于索引扫描和全表扫描速度差不多,因为读取数据时,第一种是一条一条的读取,而全表读数据时是一次加载一个 block 来读取 , 所以第二种效率会高一些。
第三个 SELECT sid FROM STUDENT WHERE SID is not null
两种方式:
第一种:索引扫描+ 读取数据(索引上的数据)
第二种:全表扫描+ 读取数据(全表)
由于索引扫描和全表扫描速度差不多,而第一种方法读取数据时,不用先找到数据在表的位置再去读,而是直接读取索引上的数据(索引上存有该索引列的数据),所以第一种方式快些。优化器选择第一种方式。
另外, SELECT * FROM STUDENT WHERE SID is not null 和 SELECT sid FROM STUDENT WHERE SID is not null 的区别就是一个选择了所有行,而另一个只选择了自己需要的行,而前一个没有利用索引,速度也很慢,后一个利用了索引。所以在写查询时,要保持良好的习惯,尽量不要用 * 号,而是把自己需要的列写出来。
3. 测试 is not null 改写成其他语句效率是否提高
有些地方有这样的说法,is not null 不能利用索引,所以要将其改写成其他语句,以便能够利用索引提高效率。下面是测试情况:
数据: 第一种情况的测试数据。
SQL 语句: SELECT sid FROM STUDENT WHERE SID is not null
改写后的SQL 语句 : SELECT sid FROM STUDENT WHERE SID > 0 and sid < 100001
可以看到两种写法的效果完全一样,所以上面的说法是错误的。
4. 总结
我们可以看到,无论是 IS NULL 还是 IS NOT NULL ,并不是如网上所说的 is null 或者 is not null 不能利用索引,而是在不同的表数据结构环境下,有可能会利用索引有可能不利用索引,而决定如何执行查询的标准就是性能。 DB2 查询优化器会评估各种查询方式的开销之后再来做决定。而且网上流传的将 IS NOT NULL 改写成其他语句的写法,也是错的,并不能提高效率。
另外,由上面测试也可以看出,要养成良好的习惯,尽量不要写 select * 而是将需要的列写上。
评论
发表评论
-
MySQL创建用户与授权
2015-12-08 19:19 1322一, 创建用户: 命令:CREATE USE ... -
数据库的拆分
2014-07-24 17:07 1125http://blog.csdn.net/bluishgl ... -
数据库事务隔离级别
2014-07-24 16:09 1051转自:http://singo107.iteye.com/b ... -
聚集索引和非聚集索引
2013-07-23 15:53 1875聚集索引和非聚集索引 聚集索引:表的物理存储按照 ... -
索引介绍
2013-07-23 14:39 1115按逻辑上来分: ... -
分区索引
2013-07-23 10:47 1258分区索引分为本地(loca ... -
反向键索引的原理和用途
2013-07-22 20:00 7302我们知道Oracle会自动为表的主键列建立索引,这个默认的 ... -
B树索引、位图索引和散列索引
2013-07-19 17:44 29834索引在数据结构上可以分为三种B树索引、位图索引和散列索引 ... -
SQLPLUS相关命令
2013-07-17 17:55 1125登录 sqlplus test/test123@MyD ... -
oracle trace文件查看
2013-07-17 17:51 1320CALL:每次SQL语句的处理都分成三个部分Parse:这步将 ... -
not in和not exists的区别
2013-05-27 13:59 2607先创建测试数据: create table test ... -
Latch (转)
2013-05-24 15:33 2506一. Latch 说明 1.1 Latc ... -
深度分析数据库的热点块问题(转)
2013-05-24 14:13 1445热点块的定义 ... -
join 条件在on和where 后的区别
2013-05-22 16:53 1285首先建两个表来测试下。 create table a( ... -
如何设计索引
2013-05-21 16:06 1640一个表建多少索引合适 ... -
重建索引
2013-05-20 23:30 1407关于索引重建,只需要记住一条: 如果它没坏,就不要 ... -
B+树索引
2013-05-20 16:10 147171.索引结构 1.1 B+树 ... -
ORACLE 循环
2012-10-12 18:39 12101、 Exit When 循环: ... -
高水位线
2012-10-08 16:38 1131所有的 oracle 段都有一个在段内容纳数据的上限 ... -
ORACLE直方图(转)
2012-10-08 13:42 1140一. 何谓直方图: ...
相关推荐
Oracle SQL 判断值为空OrNull 判断 Oracle SQL 中判断值为空...在 Oracle 和 SQL Server 中,我们可以使用 `NVL` 和 `ISNULL` 函数来判断值为空或 Null,並使用 `isNull` 和 `is not null` 来判断值是否为空或 Null。
在SQL查询语言中,`NOT EXISTS`、`NOT IN` 和 `NOT NULL` 是三种用于排除特定条件的数据记录的方法。然而,在实际应用中,这三种语法有着不同的应用场景和执行逻辑,有时初学者可能会误以为它们是等效的,但实际上...
MySQL中的`NOT IN`, `LEFT JOIN`, `IS NULL`, 和 `NOT EXISTS` 是四种不同的SQL查询方式,它们在特定情况下可以实现相似的功能,但实际执行效率可能会有很大差异。本文主要探讨这四种方法在处理大数据量时的性能表现...
在SQL语言中,IS NOT NULL和!=NULL是用于判断字段是否为NULL的两种不同表达方式,但它们在处理NULL值时的行为有所不同。了解这些差异对于编写有效的查询至关重要,特别是当处理包含NULL值的数据时。 首先,让我们...
如果将其视为一个变量名,那么“Tdsadk is not null”意味着该变量已经赋值,并非空值。这在编程语言中是一个常见的逻辑判断条件,用于确保后续操作能够安全地访问该变量。 ### 2. COM 组件对象模型 #### 2.1 定义...
本文将深入探讨如何使用`IS NULL`和`IS NOT NULL`条件来筛选含有或不含NULL值的记录。 首先,我们要了解如何设置一个字段为NULL。在MySQL中,更新字段值为NULL时,语法非常简单直接:`SET <字段名>=NULL`。例如,将...
关于性能,`NOT NULL`约束通常比`NULL`更高效,因为`NULL`值在索引和查询时需要额外的处理。在B树索引中,`NULL`值不会被存储,这可能导致索引效率下降。在进行比较操作时,`NULL`会参与计算,这可能会影响查询速度...
在IT行业中,尤其是在数据库管理和开发领域,处理空值(NULL)是常见的...通过使用`IS NULL`和`IS NOT NULL`操作符,结合逻辑运算符,以及在存储过程中封装这些逻辑,我们可以构建出更加灵活和健壮的数据库应用程序。
与原生的 `String` 类不同的是,`StringUtils` 提供了更加丰富的字符串处理功能,并且在设计上考虑到了对 `null` 值的安全处理,避免了 `NullPointerException` 的发生。这使得开发者在进行字符串处理时能够更加灵活...
"关于sql中求平均值出现null值的解决方案.txt"和"注释.txt"可能包含了更详细的解释和示例代码,而"更新说明.txt"则可能记录了这些解决方案的更新和改进。如果你在实际操作中遇到困难,可以查阅这些文件获取更多信息...
对null的特殊处理即是在前面的章节中,为了决定哪个动物不再是活着的,使用death is not null而不使用death != null的原因。 在group by中,两个null值视为相同。 执行order by时,如果运行 order by … asc,则null...
IS NOT NULL: 当列的值不为 NULL, 运算符返回 true。 <=>: 比较操作符(不同于=运算符),当比较的的两个值为 NULL 时返回 true。 关于 NULL 的条件比较运算是比较特殊的。你不能使用 = NULL 或 != NULL 在列中...
例如,在查询出征缴方式不为正划成功、倒扣成功的征收数据时,需要使用“is null”和“is not null”关键字。 了解 Oracle null 的使用是 Oracle 开发中非常重要的一部分。只有正确地理解和应用 null 的概念,才能...
总之,Python pandas库中的`isnull()`函数是检测和处理缺失值的核心工具。它能帮助我们快速定位数据中的空值,结合`any()`和`sum()`等其他函数,我们可以进一步了解数据的完整性,从而为后续的数据清洗和分析打下...
SELECT COUNT(*), COUNT(pid), COUNT(ISNULL(pid, '')) FROM tbl_user WHERE pid IS NOT NULL; ``` 结果是`(2, 2, 2)`,因为只有两行的`pid`不是`NULL`,且这两行中的`pid`被成功计数。 2. **只考虑`NULL`值的...
在进行多表联接时,必须谨慎处理这些情况,可能需要使用`COALESCE`、`IFNULL`或`ISNULL`等函数来避免Null值的影响。 在编程接口中处理数据库结果时,也需要考虑Null值。例如,在.NET环境中,使用ADO.NET访问数据库...
System.out.println("value is blank but not null"); } else { System.out.println("value is \"" + value + "\""); } } } ``` 这段代码演示了如何根据字符串的状态打印不同的消息。 此外,我们还要讨论字符...
总的来说,MySQL提供了`IS NULL`、`IS NOT NULL`和`<=>`三个工具来帮助开发者处理`NULL`值。理解和掌握这些工具,能够使你在处理含有`NULL`值的数据时更加游刃有余。在编写SQL查询时,确保正确使用这些运算符,避免...