1

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でこれを行うと、数秒以内に戻ります。

なぜこのような 2 つの異なる動作が発生するのか、この遅さを解消するにはどうすればよいでしょうか?

注: 私は常に、検索ごとに新しい 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) ascSql Developerを使用すると、同じ時間がかかります。ただし、結果の上位順は と同じNLS_SORT=BINARY_CIです。インデックスを使用UPPER('B')しましたが、何もうまくいきません。

Aの長さ = 10~15文字

B の長さ = 34 ~ 50 文字

C の長さ = 5 ~ 10 文字

A、B、C は、アプリで並べ替え可能なフィールドです。この SRC テーブルには 300 万以上のレコードがあります。最終的に、マテリアライズド ビューである SRC テーブルになりました。

SQL のビジネス ロジックはまったく問題ありません。すべてのソート テーブル フィールドとその他は、UPPER インデックスが付けられます。

4

2 に答える 2

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') )
于 2013-09-13T16:51:12.070 に答える