2012-01-27 55 views
-1

我已经做了一些搜索,但我更喜欢像一个提示或类似甲骨文:使用索引搜索空值

http://www.dba-oracle.com/oracle_tips_null_idx.htm

http://www.oracloid.com/2006/05/using-index-for-is-null/

+5

有什么问题吗? – Gerrat 2012-01-27 16:34:23

+3

@ Gik25 - 我不确定我是否理解这个问题。如果您为单个列建立索引,Oracle b-tree索引不会索引NULL值。查询中的提示无法影响索引中的行。正如您发现的那样,创建可以索引NULL值的索引的方法有多种,但这需要创建索引,并考虑搜索NULL值。 – 2012-01-27 16:36:07

+0

有兴趣引用的列中有多少个不同的值?位图索引确实存储了空值,但是它们具有自己的性能特征和怪癖,因此它们不是BTree索引的直接替代品。 – 2012-01-31 14:57:04

回答

1

如果您问“如何创建一个索引,以便在特定字段上搜索NULL值时使用该索引”,我的建议是在您感兴趣的字段上创建一个索引加主键字段。因此,如果你有一个名为A_TABLE的表,带有你想搜索NULL的字段VAL和一个名为PK的主键,我会在(VAL,PK)上创建一个索引。

分享和享受。

1

我要“答案”非 - 以上问题。

您链接的文章有点儿不对 - Oracle的b-tree索引在叶节点为空时不会捕获。就拿这个例子:

CREATE TABLE MYTABLE (
    ID NUMBER(8) NOT NULL, 
    DAT VARCHAR2(100) 
); 

CREATE INDEX MYTABLE_IDX_1 ON MYTABLE (DAT); 

/* Perform inserts into MYTABLE where some DAT are null */ 

SELECT COUNT(*) FROM MYTABLE WHERE DAT IS NULL; 

期末SELECT将无法​​使用该索引,因为叶子(最右列)将不会捕捉到零点。 Burleson的解决方案很愚蠢,因为现在您必须在所有查询中使用NVL,并损害了表中的数据。戈尔巴乔夫的方法包括一个已知的NOT NULL列的树的树叶,但这无缘无故扩大索引。也许在他的情况下,索引对于调整其他查询是有意义的,但是如果你想要做的只是找到NULL,那么最简单的解决方案就是让叶子保持不变。

CREATE INDEX MYTABLE_IDX_1 ON MYTABLE (DAT, 1); 

现在,叶子都是恒定的(1),默认情况下的空都将一起(无论是在顶部或指数的底部,但它其实并不重要,因为可以使用Oracle该指数向前或向后)。这个常数存在轻微的存储损失,但是单个数字比典型表中的大多数其他数据字段要小。现在数据库可以在查询空值时使用索引......如果优化器找到获取数据的最佳方式。

+0

我对索引中第二个字段使用常量的担心是,它可能会导致DELETE过程缓慢,因为可能会按顺序搜索所有重复项。我在其他数据库产品中遇到过问题 - 不确定这是否是Oracle的问题。 – 2012-01-27 17:45:27

+0

索引将始终(幕后)将创建索引条目的记录的ROWID存储为最后一个“列”。也就是说,数据库不需要顺序遍历索引中的所有(NULL,1)条目,因为ROWID也包含在排序中。 – 2012-01-27 18:02:57

+0

很高兴知道 - 谢谢! – 2012-01-27 18:05:58

2

如何使用NVL2的功能索引,如;

CREATE TABLE foo (bar INTEGER); 
INSERT INTO foo VALUES (1); 
INSERT INTO foo VALUES (NULL); 
CREATE INDEX baz ON foo (NVL2(bar,0,1)); 

然后;

DELETE plan_table; 
EXPLAIN PLAN FOR SELECT * FROM foo WHERE NVL2(bar,0,1) = 1; 
SELECT operation, object_name FROM plan_table; 

应该给你

OPERATION  OBJECT_NAME 
---------------- ----------- 
SELECT STATEMENT 
TABLE ACCESS  FOO 
INDEX   BAZ  << yep