我正在使用Oracle 11gR2和Hibernate 4.2.1。 我的应用程序是一个搜索应用程序。
只有SELECT操作,所有这些操作都是本机查询。
Oracle默认使用区分大小写的排序。 我想将其覆盖为不区分大小写。
我在这里看到了几个选项http://docs.oracle.com/cd/A81042_01/DOC/server.816/a76966/ch2.htm#91066
现在我在执行任何搜索之前都在使用此查询。
ALTER SESSION SET NLS_SORT='BINARY_CI'
如果我在执行搜索查询之前执行上面的sql,则hibernate从搜索查询返回大约需要15分钟。 如果我在Sql Developer中这样做,它会在几秒钟内返回。
为什么会出现这两种不同的行为, 我该怎么做才能摆脱这种缓慢的过程?
注意:我总是为每次搜索打开一个新的Hibernate会话。
这是我的sql:
SELECT *
FROM (SELECT
row_.*,
rownum rownum_
FROM (SELECT
a, b, c, d, e,
RTRIM(XMLAGG(XMLELEMENT("x", f || ', ') ORDER BY f ASC)
.extract('//text()').getClobVal(), ', ') AS f,
RTRIM(
XMLAGG(XMLELEMENT("x", g || ', ') ORDER BY g ASC)
.extract('//text()').getClobVal(), ', ') AS g
FROM ( SELECT src.a, src.b, src.c, src.d, src.e, src.f, src.g
FROM src src
WHERE upper(pp) = 'PP'
AND upper(qq) = 'QQ'
AND upper(rr) = 'RR'
AND upper(ss) = 'SS'
AND upper(tt) = 'TT')
GROUP BY a, b, c, d, e
ORDER BY b ASC) row_
WHERE rownum <= 400
) WHERE rownum_ > 0;
有可能字段带有LIKE操作,它是一个动态的SQL查询。如果我使用order by upper(B) asc
Sql Developer也需要同样的时间。
但按上限结果排序与NLS_SORT=BINARY_CI
相同。我使用了UPPER('B')
个索引,但不会对我有用。
A的长度= 10-15个字符
B的长度= 34-50个字符
C的长度= 5-10个字符
A,B和C是通过app排序的字段。 该SRC表有300万条记录。 我们最终得到了一个物化视图的SRC表。
SQL的业务逻辑完全正常。 所有sor-table字段和其他字段都是UPPER索引。
答案 0 :(得分:1)
UPPER()和BINARY_CI可能会产生相同的结果,但Oracle无法互换使用它们。要使用索引和BINARY_CI,您必须创建如下索引:
create index src_nlssort_index on src(nlssort(b, 'nls_sort=''BINARY_CI'''));
示例表和大小写混合数据
create table src(b varchar2(100) not null);
insert into src select 'MiXeD CAse '||level from dual connect by level <= 100000;
默认情况下,upper()谓词可以对upper()索引执行范围扫描
create index src_upper_index on src(upper(b));
explain plan for
select * from src where upper(b) = 'MIXED CASE 1';
select * from table(dbms_xplan.display(format => '-rows -bytes -cost -predicate
-note'));
Plan hash value: 1533361696
------------------------------------------------------------------
| Id | Operation | Name | Time |
------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| SRC | 00:00:01 |
| 2 | INDEX RANGE SCAN | SRC_UPPER_INDEX | 00:00:01 |
------------------------------------------------------------------
BINARY_CI和LINGUISTIC不会使用索引
alter session set nls_sort='binary_ci';
alter session set nls_comp='linguistic';
explain plan for
select * from src where b = 'MIXED CASE 1';
select * from table(dbms_xplan.display(format => '-rows -bytes -cost -note'));
Plan hash value: 3368256651
---------------------------------------------
| Id | Operation | Name | Time |
---------------------------------------------
| 0 | SELECT STATEMENT | | 00:00:02 |
|* 1 | TABLE ACCESS FULL| SRC | 00:00:02 |
---------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(NLSSORT("B",'nls_sort=''BINARY_CI''')=HEXTORAW('6D69786564
2063617365203100') )
NLSSORT()上基于函数的索引启用索引范围扫描
create index src_nlssort_index on src(nlssort(b, 'nls_sort=''BINARY_CI'''));
explain plan for
select * from src where b = 'MIXED CASE 1';
select * from table(dbms_xplan.display(format => '-rows -bytes -cost -note'));
Plan hash value: 478278159
--------------------------------------------------------------------
| Id | Operation | Name | Time |
--------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| SRC | 00:00:01 |
|* 2 | INDEX RANGE SCAN | SRC_NLSSORT_INDEX | 00:00:01 |
--------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access(NLSSORT("B",'nls_sort=''BINARY_CI''')=HEXTORAW('6D69786564
2063617365203100') )
答案 1 :(得分:1)
我调查并发现参数NLS_COMP和NLS_SORT可能会影响oracle如何使用字符串的执行计划(当它比较或排序时)。
不需要更改NLS会话。加入
ORDER BY NLSSORT(column , 'NLS_SORT=BINARY_CI')
并为NLS添加索引就足够了
create index column_index_binary as NLSSORT(column , 'NLS_SORT=BINARY_CI')
我发现了这个问题的线索,所以我还清了。
Why oracle stored procedure execution time is greatly increased depending on how it is executed?