Oracle
 sql >> Base de données >  >> RDS >> Oracle

Pourquoi l'index NLSSORT n'est-il pas utilisé pour cette requête ?

Les expressions sont converties en paramètres de session NLS dans DML, mais pas dans DDL.

Il s'agit sans doute d'un bogue avec le comportement de NLSSORT(char, 'NLS_SORT=BINARY') .
D'après le manuel :"Si vous spécifiez BINARY, alors cette fonction renvoie char."Mais ce n'est pas vrai pour l'indice. Normalement, il est très pratique que l'expression d'index ne subisse aucune transformation; si cela dépendait des paramètres de session, des outils comme DBMS_METADATA.GET_DDL devraient renvoyer de nombreux alter session déclarations. Mais dans ce cas, cela signifie que vous pouvez créer un index qui ne sera jamais utilisé.

Le plan d'explication montre le réel expression. Voici comment Oracle utilise nlssort dans une session sans qu'il soit explicitement utilisé :

alter session set nls_comp=linguistic;
alter session set nls_sort=binary_ai;
drop table raw_screen;
create table raw_screen (
   id   number(10)     constraint rscr_pk primary key,
   name nvarchar2(256) not null
);
create unique index idx_binary_ai
      on raw_screen (nlssort(name, 'nls_sort=binary_ai'));
explain plan for select * from raw_screen where name = n'raw_screen1000';
select * from table(dbms_xplan.display(format=>'basic predicate'));

Plan hash value: 2639454581

-----------------------------------------------------
| Id  | Operation                   | Name          |
-----------------------------------------------------
|   0 | SELECT STATEMENT            |               |
|   1 |  TABLE ACCESS BY INDEX ROWID| RAW_SCREEN    |
|*  2 |   INDEX UNIQUE SCAN         | IDX_BINARY_AI |
-----------------------------------------------------

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

   2 - access(NLSSORT("NAME",'nls_sort=''BINARY_AI''')=HEXTORAW('0072006
              10077005F00730063007200650065006E003100300030003000'))

Cet exemple montre que nlssort(char, 'nls_sort=binary') est supprimé par le DML :

alter session set nls_comp=linguistic;
alter session set nls_sort=binary_ai;
drop table raw_screen;
create table raw_screen (
   id   number(10)     constraint rscr_pk primary key,
   name nvarchar2(256) not null
);
create unique index idx_binary_ai on
      raw_screen (nlssort(name, 'nls_sort=binary_ai'));
explain plan for select * from raw_screen where
  nlssort(name,'nls_sort=binary') = nlssort(N'raw_screen1000','nls_sort=binary');
select * from table(dbms_xplan.display(format=>'basic predicate'));

Plan hash value: 237065300

----------------------------------------
| Id  | Operation         | Name       |
----------------------------------------
|   0 | SELECT STATEMENT  |            |
|*  1 |  TABLE ACCESS FULL| RAW_SCREEN |
----------------------------------------

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

   1 - filter("NAME"=U'raw_screen1000')

En résumé - l'index DDL doit correspondre exactement au transformé expressions, qui peuvent dépendre des paramètres de session et du comportement inhabituel de binary .