2012-02-09 42 views
0

我有很多列的表,我的查詢是這樣的如何在oracle的列上進行索引是不是空值查詢?

select * from (select my_table_id from my_table where start_time_local>=? 
and type_pk<>? and rule_pk=? and this_.name is not null order by start_time_gmt 
desc) where rownum <= ? 

如果我創建

(start_time_local, type_pk, rule_pk, name) 

索引這將是低效的,因爲名字是一個varchar(1024)。有沒有指標更好的方法上是這樣的:

(start_time_local, type_pk, rule_pk, isNotNull(name)) 

感謝,

+0

你確定索引是否合適?如果行在該列中有NULL,那麼百分比是多少?如果百分比很低,那麼oracle會無視這個索引。 – skaffman 2012-02-09 11:03:36

回答

2

通常,對於查詢的最佳指標是對where子句中的一切指標在降低選擇性然後一切秩序order by按照選擇性降低的順序,然後選擇您尚未編入索引的所有內容。這意味着你將只使用索引而不是它後面的表。

該方法可以,但是,完全荒謬的。這取決於你想要走多遠。

Selective裝置多少個值有在指數中的行的總數的百分比。一般來說,列中的值越多,查找索引的速度就越快。我通常說,因爲每個規則都有總是例外。

例如如果rule_pk是你的表的主鍵,然後它很可能是足以指數此列。這意味着你要做一個獨特的索引掃描,然後通過rowid進行表訪問。

繼續承擔rule_pk是主鍵,start_time_local幾乎是獨一無二的,在其他列也同樣選擇了最佳指數會是這樣的: (rule_pk, start_time_local, type_pk, this_.name, start_time_gmt, my_table_id)。儘管這很荒謬。

我建議閱讀如何閱讀解釋計劃,並定期使用它們的文檔this一部分。

也不要忘記創建索引後,收集的統計數據,因爲這可以使一個很大的區別:

dbms_stats.gather_table_stats('SCHEMA_NAME' 
          , 'TABLE_NAME' 
          , cascade => True 
          , method_opt => 'FOR ALL INDEXED COLUMNS' 
           ); 

應該足夠了。

2

如果一個字段將被搜索NOT NULL,從來沒有一個實際值,你可以使用基於函數的索引以節省空間索引(以及可能通過更好地利用高速緩存提高性能)。例如:

CREATE TABLE THE_TABLE (
    ID INT PRIMARY KEY, 
    THE_FIELD VARCHAR2(20) 
); 

CREATE INDEX THE_TABLE_IE1 ON THE_TABLE(NVL2(THE_FIELD, 'Y', 'N')) COMPRESS; 

(將會有許多重複的「Y」和「N」中的指標值,所以可能是值得到COMPRESS索引,如上所示。)

,然後選擇這樣的:

SELECT * FROM THE_TABLE WHERE NVL2(THE_FIELD, 'Y', 'N') = 'Y' -- Equivalent to THE_FIELD IS NOT NULL 
SELECT * FROM THE_TABLE WHERE NVL2(THE_FIELD, 'Y', 'N') = 'N' -- Equivalent to THE_FIELD IS NULL 

如果您不需要搜索NULL,你大概可以擠一些更多的空間效率是這樣的:

CREATE INDEX THE_TABLE_IE1 ON THE_TABLE(NVL2(THE_FIELD, 'Y', NULL)) COMPRESS; 
SELECT ID FROM THE_TABLE WHERE NVL2(THE_FIELD, 'Y', NULL) = 'Y' -- Equivalent to THE_FIELD IS NOT NULL 

Oracle不索引NULL(在基於B樹的索引中),所以NVL2(THE_FIELD,'Y',NULL)將會完全消除來自索引的THE_FIELD IS NULL行。

相關問題