2013-12-12 35 views
3

在我們的應用中有會話級配置不區分大小寫的語義:爲什麼NLSSORT索引不用於此查詢?

alter session set NLS_COMP=LINGUISTIC; 
alter session set NLS_SORT=BINARY_AI; 

但我希望能有與二元語義的名字列的表,所以我相應地定義一個基於函數的索引:

create table RAW_SCREEN (
    ID number(10)  constraint RSCR_PK primary key, 
    NAME nvarchar2(256) not null 
); 
create unique index RSCR_IDX on RAW_SCREEN (nlssort(NAME, 'NLS_SORT=BINARY')); 

我本來期望下面的查詢採取基於函數的索引的優勢:

select * from RAW_SCREEN where 
    nlssort(NAME, 'NLS_SORT=BINARY') = nlssort(N'raw_screen1', 'NLS_SORT=BINARY'); 

但沒有。查詢計劃顯示錶掃描。雖然實驗,我發現,在名稱的簡單指標的伎倆:

create unique index RSCR_IDX2 on RAW_SCREEN (NAME); 

當再次運行查詢,成功地使用了RSCR_IDX2指數。

現在,這並不令人感到意外,但我不明白爲什麼第一個基於函數的索引沒有被優化器使用。索引表達式與WHERE條件中使用的表達式完全匹配。你有什麼想法,爲什麼它不被使用?

注意:這是在Oracle運行10.2

這裏是一個完整的測試腳本,如果你想嘗試一下:

alter session set NLS_COMP=LINGUISTIC; 
alter session set NLS_SORT=BINARY_AI; 

create table RAW_SCREEN (
    ID     number(10)   constraint RSCR_PK primary key, 
    NAME     nvarchar2(256)  not null 
); 

create unique index RSCR_IDX on RAW_SCREEN (nlssort(NAME, 'NLS_SORT=BINARY')); 
--create unique index RSCR_IDX2 on RAW_SCREEN (NAME); 

begin 
    for i in 1..10000 
    loop 
    insert into RAW_SCREEN values (i, 'raw_screen' || i); 
    end loop; 
end; 
/
commit; 

select * from RAW_SCREEN where nlssort(NAME, 'NLS_SORT=BINARY') = nlssort(N'raw_screen1000', 'NLS_SORT=BINARY'); 

回答

1

表達式轉換爲在DML NLS會話設置,而不是在DDL 。

這可能是一個錯誤,其行爲爲NLSSORT(char, 'NLS_SORT=BINARY')
the manual:「如果指定BINARY,則此函數返回char。」 但是,這是而不是對索引爲true。通常,索引表達式不經過任何轉換非常方便;如果它依賴會話設置 而不是像DBMS_METADATA這樣的工具.GET_DDL將不得不返回許多alter session語句。但在這種情況下,這意味着您可以創建一個永遠不會使用 的索引。

解釋計劃顯示真實表達式。這裏是甲骨文在會話如何使用nlssort沒有它明確地使用:

alter session set nls_comp=linguistic; 
alter session set nls_sort=binary_ai; 
drop table raw_screen; 
create table raw_screen (
    id number(10)  constraint rscr_pk primary key, 
    name nvarchar2(256) not null 
); 
create unique index idx_binary_ai 
     on raw_screen (nlssort(name, 'nls_sort=binary_ai')); 
explain plan for select * from raw_screen where name = n'raw_screen1000'; 
select * from table(dbms_xplan.display(format=>'basic predicate')); 

Plan hash value: 2639454581 

----------------------------------------------------- 
| Id | Operation     | Name   | 
----------------------------------------------------- 
| 0 | SELECT STATEMENT   |    | 
| 1 | TABLE ACCESS BY INDEX ROWID| RAW_SCREEN | 
|* 2 | INDEX UNIQUE SCAN   | IDX_BINARY_AI | 
----------------------------------------------------- 

Predicate Information (identified by operation id): 
--------------------------------------------------- 

    2 - access(NLSSORT("NAME",'nls_sort=''BINARY_AI''')=HEXTORAW('0072006 
       10077005F00730063007200650065006E003100300030003000')) 

這個例子表明,nlssort(char, 'nls_sort=binary')由DML下降:

alter session set nls_comp=linguistic; 
alter session set nls_sort=binary_ai; 
drop table raw_screen; 
create table raw_screen (
    id number(10)  constraint rscr_pk primary key, 
    name nvarchar2(256) not null 
); 
create unique index idx_binary_ai on 
     raw_screen (nlssort(name, 'nls_sort=binary_ai')); 
explain plan for select * from raw_screen where 
    nlssort(name,'nls_sort=binary') = nlssort(N'raw_screen1000','nls_sort=binary'); 
select * from table(dbms_xplan.display(format=>'basic predicate')); 

Plan hash value: 237065300 

---------------------------------------- 
| Id | Operation   | Name  | 
---------------------------------------- 
| 0 | SELECT STATEMENT |   | 
|* 1 | TABLE ACCESS FULL| RAW_SCREEN | 
---------------------------------------- 

Predicate Information (identified by operation id): 
--------------------------------------------------- 

    1 - filter("NAME"=U'raw_screen1000') 

總結 - 指數DDL需要精確匹配轉換爲表達式,這可能取決於會話設置和binary的異常行爲。

相關問題