我们在“varchar2”列上使用“nls_sort”功能索引。当我们尝试获取唯一值时,索引性能与普通(非功能性)索引一样好。但是,当我们尝试在“nls_sort”功能索引上编写带有“范围扫描”计划的查询时,我们会遇到严重的性能损失。我准备了一个最小的测试用例来查明问题。
create table scott.nls_test (nls_col varchar2(50));
begin
for i in 1 .. 5000000
loop
insert into scott.nls_test values ('ABC' || dbms_random.string('a', 47));
end loop;
for i in 1 .. 50
loop
insert into scott.nls_test values ('GHI' || dbms_random.string('a', 47));
end loop;
for i in 1 .. 5000000
loop
insert into scott.nls_test values ('XYZ' || dbms_random.string('a', 47));
end loop;
end;
create index nls_test_idx0 on scott.nls_test(nlssort(nls_col, 'nls_sort=''XTURKISH_AI'''))
create index nls_test_idx1 on scott.nls_test(nls_col);
alter session set nls_sort = 'XTURKISH_AI';
alter session set nls_comp = 'LINGUISTIC';
在我们的系统中,以下查询在 5.8 秒内运行
select count(1) from scott.nls_test where nls_col like 'GHI%';
--INDEX RANGE SCAN | NLS_TEST_IDX0 | 39751
当我们切换到二进制
alter session set nls_sort = 'BINARY';
select count(1) from scott.nls_test where nls_col like 'GHI%';
--INDEX RANGE SCAN| NLS_TEST_IDX1 | 50
这次相同的查询在 0.078 秒内运行。是否存在我们遗漏的关于“nls_sort”功能索引的已知问题?你觉得这种行为正常吗?