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

时间:2009-09-04 15:50:20

标签: 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'));
/   

- 默认设置

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
/

- 语言

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
/

2 个答案:

答案 0 :(得分:2)

由于Oracle 11g - LIKE CAN 使用语言索引。 文档被修改为:

The SQL functions MAX( ) and MIN( ) cannot use linguistic indexes when NLS_COMP is set to LINGUISTIC

请注意,他们删除了“以及LIKE运算符”部分。

答案 1 :(得分:1)

我已在我的测试数据库(10.2.0.3)上复制了您的发现。经过调查,似乎LIKE运算符无法使用语言索引 - 来自10gR2 Documentation

  

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

语言索引的主要目的似乎是改进SORT操作。

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

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

修改:还有另一种解决方法:您可以将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:
--------------------------------------------------------------------------------

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