ORACLE - 如何创建在NLS_COMP = Linguistic和NLS_Sort = Binary_CI时将使用的索引

5 sql oracle plsql

默认情况下,Oracle使用创建的索引

当我改为NLS_COMP = Linguistic和NLS_Sort = Binary_CI时,我得到全表扫描.

我在某处读到了使用(nlssort(name,'NLS_SORT = BINARY_CI'))创建索引; 会工作.

正如我在下面的尝试所示,并非如此.即使我强迫它,性能似乎也不是我所期望的.这是一个简单的例子我喜欢为具有数百万行的表解决这个问题,因此全表扫描会很糟糕.

所以问题是如何构建索引以便使用它们.

谢谢

- 安装X.

create table x ( name varchar2(30)) ;
insert into x select table_name from all_tables;
create index x_ix on x (name);
create index x_ic on x (nlssort(name, 'NLS_SORT=BINARY_CI'));
/   
Run Code Online (Sandbox Code Playgroud)

- 默认设置

ALTER SESSION SET NLS_COMP=BINARY;
ALTER SESSION SET NLS_SORT=BINARY; 
/
set autotrace on 
/
select * from X where NAME like 'x%';

--0 rows selected
--
---------------------------------------------------------------------------
--| Id  | Operation        | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
--|   0 | SELECT STATEMENT |      |     1 |    17 |     1   (0)| 00:00:01 |
--|*  1 |  INDEX RANGE SCAN| X_IX |     1 |    17 |     1   (0)| 00:00:01 |
---------------------------------------------------------------------------
/
set autotrace off
/
Run Code Online (Sandbox Code Playgroud)

- 语言学

ALTER SESSION SET NLS_COMP=LINGUISTIC; 
ALTER SESSION SET NLS_SORT=BINARY_CI; 
/
set autotrace on
/
select * from X where NAME like 'x%';
--13 rows selected
--
----------------------------------------------------------------------------
--| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
--|   0 | SELECT STATEMENT  |      |     1 |    17 |     3   (0)| 00:00:01 |
--|*  1 |  TABLE ACCESS FULL| X    |     1 |    17 |     3   (0)| 00:00:01 |
----------------------------------------------------------------------------

select /*+ INDEX( X  X_IX           ) */ * from X where   NAME like 'x%';
--13 rows selected
--
---------------------------------------------------------------------------
--| Id  | Operation        | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
--|   0 | SELECT STATEMENT |      |     1 |    17 |     9   (0)| 00:00:01 |
--|*  1 |  INDEX FULL SCAN | X_IX |     1 |    17 |     9   (0)| 00:00:01 |
---------------------------------------------------------------------------

select /*+ INDEX( X  X_IC           ) */ * from X where   NAME like 'x%'; 
--13 rows selected
--
--------------------------------------------------------------------------------------
--| Id  | Operation                   | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
--|   0 | SELECT STATEMENT            |      |     1 |    17 |   448   (1)| 00:00:06 |
--|*  1 |  TABLE ACCESS BY INDEX ROWID| X    |     1 |    17 |   448   (1)| 00:00:06 |
--|   2 |   INDEX FULL SCAN           | X_IC |  1629 |       |     8   (0)| 00:00:01 |
--------------------------------------------------------------------------------------
/

set autotrace off
/
Run Code Online (Sandbox Code Playgroud)

Vin*_*rat 1

我已在我的测试数据库(10.2.0.3)上重现了您的发现。经过调查,操作员似乎无法使用来自10gR2 文档的LIKE语言索引:

当 NLS_COMP 设置为 LINGUISTIC 时,SQL 函数 MAX( ) 和 MIN( ) 以及 LIKE 运算符无法使用语言索引。

看来语言索引的主要目的是改进排序操作。

如果您的目标是以不区分大小写的方式搜索此列,我建议您创建一个索引UPPER(name)并使用它来构建查询UPPER(name) LIKE UPPER('x%')

如果您想使用其他(更复杂的)语言设置,您可能需要查看Oracle Text 索引

编辑:还有另一种解决方法:您可以将其替换LIKE 'ABC%'为:

SQL> select * from x where name >= 'ABC' and name < 'ABD';

Execution Plan
----------------------------------------------------------
Plan hash value: 708878862

--------------------------------------------------------------------------------
| Id  | Operation                   | Name | Rows  | Bytes | Cost (%CPU)| Time  
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |      |     1 |    24 |     4   (0)| 00:00:
|   1 |  TABLE ACCESS BY INDEX ROWID| X    |     1 |    24 |     4   (0)| 00:00:
|*  2 |   INDEX RANGE SCAN          | X_IC |     1 |       |     3   (0)| 00:00:
--------------------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,如果您可以将 LIKE 表达式转换为带有比较运算符 (><) 的表达式,则可能会使用语言索引。