2012-02-07 29 views
7

我有一個空的列的索引,我想選擇所有它的價值觀是這樣的:指數爲空列

SELECT e.ename 
FROM emp e; 

在解釋計劃我看到一個FULL TABLE SCAN(甚至一個暗示沒有幫助)

SELECT e.ename 
FROM emp e 
WHERE e.ename = 'gdoron'; 

是否使用索引...

我用Google搜索,發現有沒有空條目索引,因此第一查詢不能使用索引。

我的問題很簡單:爲什麼不在索引空條目?

+1

另外,整個表格可以在您的第一個示例中執行,因爲您從表格中選擇大部分記錄(在您的案例中爲100%)。無論您是否具有空值索引,優化程序都會爲此查詢選擇FTS並不重要。 – Ollie 2012-02-07 11:49:49

+0

@Ollie。這就是我寫的,我有'hint'再次嘗試過了,它並沒有幫助... – gdoron 2012-02-07 11:51:04

+1

好,典型的B樹索引將不會包含空值。位圖索引將索引空值。 – tbone 2012-02-07 12:00:40

回答

14

默認情況下,關係數據庫忽略空值(因爲關係模型說,NULL意味着「不存在」)。因此,Index不會存儲NULL值,因此如果在SQL語句中有空條件,則會忽略相關索引(默認情況下)。

但是你可以suprass此問題,檢查THISTHIS文章。

+0

我讀過這篇文章,這就是爲什麼我問爲什麼這樣工作。有點奇怪。 – gdoron 2012-02-07 11:47:23

+1

想一想,在一個索引中,它們如何區別於所有的NULL? – 2012-02-07 13:02:00

2

如果你得到所有從表中的行,爲什麼你認爲它應該使用索引?全表掃描是返回所有值的最有效方法。它與沒有處於索引中的空值無關,並且與優化器選擇檢索數據的最有效方式有關。


@ A.B.Cade:這有可能是優化器可以選擇使用該索引,但不太可能。假設您有一張帶有100行索引表的表,但只有10個值。如果優化器使用索引,則必須從索引中獲取10行,然後將其擴展爲100行,而使用全表掃描時,它將從起始處獲取所有100行。這裏有一個例子:

create table test1 (blarg varchar2(10)); 

create index ak_test1 on test1 (blarg); 

insert into test1 
select floor(level/10) from dual connect by level<=100; 

exec dbms_stats.gather_table_stats('testschema','test1'); 

exec dbms_stats.gather_index_stats('testschema','ak_test1'); 

EXPLAIN PLAN FOR 
select * from test1; 

我的觀點在很大程度上,這個問題在很大程度上是基於對一個有缺陷的前提:即索引掃描本質上是較好的全表掃描。這並非總是如此,正如這種情況所表明的那樣。

+0

請參閱DaveCosta的評論。他正在查詢索引列 - 如果不是空值,它會使用INDEX FULL SCAN – 2012-02-07 14:33:28

+0

嗯,我們不能說它肯定會使用索引,只是它可能有。 – 2012-02-07 14:51:45

+0

我同意,但他在問題中提到「(甚至暗示沒有幫助)」 – 2012-02-08 07:32:27

0

我不知道第一個查詢相關的指數使用方面,至少第二可能。

不管怎麼說,這是事實,你不能索引包含空值的列,有很多方法可以做到這一點像,例如:

create index MY_INDEX on emp(ename, 1); 

通知, 1)在這做的伎倆結束。

+0

你不是這個意思:'在emp上創建索引MY_INDEX(NVL(ename,'null'));' – gdoron 2012-02-07 16:58:57

+0

nope。後面跟着數字1的逗號是正確的形式。而不需要使用nvl。 nvl是另一個使用它的技巧,但它會強制用戶與字符串'null'進行比較,如果在寫入時使用它。 – Farid 2012-02-07 17:08:22