在我们的应用程序中,我们在会话级别配置了不区分大小写的语义:
alter session set NLS_COMP=LINGUISTIC;
alter session set NLS_SORT=BINARY_AI;
但是我希望有一个带有二进制语义的NAME列的表,所以我相应地定义了一个基于函数的索引:
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');
但事实并非如此.查询计划显示表扫描.在进行实验时,我发现NAME上的一个简单索引可以解决问题:
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');
最佳答案 表达式在DML中转换为NLS会话设置,但在DDL中不转换.
这可以说是NLSSORT行为的一个错误(char,’NLS_SORT = BINARY’).
从the manual:“如果指定BINARY,则此函数返回char.”
但指数并非如此.通常,索引表达式不经历任何转换是非常方便的;如果它取决于会话设置
比DBMS_METADATA.GET_DDL这样的工具必须返回许多alter session语句.但在这种情况下,这意味着您可以创建永远不会的索引
使用.
解释计划显示了真实的表达方式.以下是Oracle在会话中如何使用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'))
此示例显示DML删除了nlssort(char,’nls_sort = binary’):
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需要与转换后的表达式完全匹配,这可能取决于会话设置和二进制的异常行为.