SQL优化:NULL值与索引的使用

发布时间:2011-12-04 03:43:21,浏览3999次,转载自:ITEYE

NULL是数据库中特有的数据类型,当一条记录的某个列为NULL,则表示这个列的值是未知的、是不确定的。简单的说,由于NULL存在着无数的可能,因此两个NULL不是相等的关系,同样也不能说两个NULL就不相等,或者比较两个NULL的大小,这些操作都没有意义,得不到一个确切的答案。

那么,一个字段有可能存在空值是否适合创建索引呢?

大多数人都听说过这样一句话,索引不存储NULL值。这句话其实比不严谨。如果采用比较严谨的方式来说:B树索引不存储索引列全为空的记录。如果把这句话用在单列索引上,就是前面提到的B树索引不存储NULL。

首先索引分为BTREE和BITMAP两种,对于BTREE索引,是不存储NULL值的,而BITMAP索引,则存储NULL值。其次,从索引列的个数来划分,索引分为单列索引和复合索引,对于单列索引来说很简单,如果一条记录中这个索引字段为空,那么索引不会保存这条记录的信息。但是对于复合索引,由于存在着多个列,如果某一个索引列不为空,那么索引就会包括这条记录,即使其他所有的所有列都是NULL值。

究竟日常应用中对可能为空的列如何创建索引,ORACLE又如何使用这些索引呢?经过测试,简单总结为以下两点:

I:对于经常单列访问字段中非空值的情况,直接创建单列索引。
II:对于经常查询字段IS NULL又希望使用索引的情况,则需要结合查询条件选择合适的非空字段创建组合索引。

同时,在日常应用中请注意:

I: 如果要查询一个表的记录数,可以通过全表扫描的方法,也可以通过COUNT非空列记录数的方法,如果此时非空列上存在索引,就可以直接访问索引获得数据。
II: 要查询一个可能为空字段的非空记录数,如果该列上建立了单列索引,直接访问索引可以获得数据,但若想通过索引获得该列所有的记录数(即全表数据量),即使你固定执行了计划,强制走该列的索引,Oracle也会自动选择全表扫描。这应该也是我们倡导不可能为空的字段一定要添加非空约束的原因之一吧。
评论