Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/.htaccess/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oracle11g 使用复合索引时如何避免排序?_Oracle11g_Sql Execution Plan - Fatal编程技术网

Oracle11g 使用复合索引时如何避免排序?

Oracle11g 使用复合索引时如何避免排序?,oracle11g,sql-execution-plan,Oracle11g,Sql Execution Plan,创建测试表: create table customer (first_name varchar2(20), last_name varchar2(20) not null, address varchar(20)); insert into customer select dbms_random.string('U', 20), dbms_random.string('U', 20), dbms_random.string('U', 20) from dual connect by leve

创建测试表:

create table customer (first_name varchar2(20), last_name varchar2(20) not null, address varchar(20));

insert into customer select dbms_random.string('U', 20), dbms_random.string('U', 20), dbms_random.string('U', 20) from dual connect by level <= 100000;
commit;

create index i_ln_fn_0 on customer(last_name, first_name,0); — just to be sure that all rows are indexed
但因为我只想要第一行,所以我想避免整张桌子。我想有一个这样的计划:

SELECT STATEMENT
    TABLE ACCESS BY ROWID (customer)
        INDEX FULL SCAN (i_ln_fn_0)
如何说服db避免这种情况

问题更严重。即使我只使用姓氏,在任何地方:

explain plan for
select /*+ FIRST_ROWS(20) */ last_name
  from CUSTOMER
  where last_name like 'AB%'
    and last_name is not null
  order by last_name;

select * from table(dbms_xplan.display);

-------------------------------------------------------------------------------
| Id  | Operation         | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |           |    17 |   357 |     4  (25)| 00:00:01 |
|   1 |  SORT ORDER BY    |           |    17 |   357 |     4  (25)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN| I_LN_FN_0 |    17 |   357 |     3   (0)| 00:00:01 |
-------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("LAST_NAME" LIKE 'AB%')
       filter("LAST_NAME" LIKE 'AB%')
在这里,排序实际上是不必要的,但db仍然使用它。为什么?

编辑:在两个系统上都进行了测试

Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
PL/SQL Release 11.2.0.1.0 - Production
"CORE 11.2.0.1.0 Production"
TNS for 64-bit Windows: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production


使用相同的计划。

原因是NLS_排序参数的值错误。在将其更改为二进制后,计划开始看起来像我想要的

发件人:

NLS_SORT的值会影响查询的执行计划。因为 标准索引不能用作在索引中排序的值的源 语言顺序,通常必须执行显式排序操作 而不是索引范围扫描。NLSSORT上的函数索引 函数可以定义为提供按语言顺序排序的值 并将索引范围扫描重新引入执行计划


(我在forums.oracle.com上从Paul Horth那里得到了这个答案。)

我无法复制您的结果。事实上,我通过
索引全扫描
得到了您想要的计划。您使用的Oracle的确切版本是什么?你有没有遗漏任何统计数据?奇怪的是,您没有在谓词信息部分获得用于此语句的
动态采样(level=2)
。您是否将参数优化器_dynamic_sampling更改为0?奇怪,因为我可以在我的个人(笔记本)和生产数据库(我在原始问题中添加了db版本)上重现该问题。据我所知,数据库中没有任何不寻常的调整。在V$参数中,所有重要内容都有默认值,优化器_dynamic_sampling=2。我使用
execdbms\u stats.gather\u table\u stats('TEST','CUSTOMER',cascade=>true)重新收集统计数据但没有任何效果。
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
PL/SQL Release 11.2.0.1.0 - Production
"CORE 11.2.0.1.0 Production"
TNS for 64-bit Windows: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production+
PL/SQL Release 11.2.0.2.0 - Production+
"CORE 11.2.0.2.0Production"+
TNS for IBM/AIX RISC System/6000: Version 11.2.0.2.0 - Production+
NLSRTL Version 11.2.0.2.0 - Production+