默认情况下,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)
我已在我的测试数据库(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 表达式转换为带有比较运算符 (>和<) 的表达式,则可能会使用语言索引。
| 归档时间: |
|
| 查看次数: |
6297 次 |
| 最近记录: |