Super clanek.
Nevim jak v postgre, ale u tech typu (u mssql) bych jeste pridal poznatek, ze typ muze byt totozny, ale u textu zalezi i na collation (tedy, jestli ma byt porovnani case sensitive, pripadne accent sensitive, pripadne jaka je code page). Pri rozdilnosti pak musi server taky vicemene provadet scan (pokud se jedna o join).
Na prvni pohled to neni videt, protoze se pri definici typu pro tabulku/promennou pouzije default collation (vlastnost databaze). Pri rozdilnosti sice server upozorni, ze se musi jeden z nich vybrat, ale programator tam vetsinou bez rozmyslu hodi jednu z nich, misto toho aby se zamyslel nad tim, ktera tabulka bude v budoucnu mensi a proto bude jeji scan lacinejsi. (pripadne se zamyslel nad tim, jestli vubec ma mit ruzne collation v databazi)
Oracle má také jednu extra vrstvu legrace ve chvíli, kdy se nastaví, že je case-insensitive. On stále v datech bude mít mix velkých a malých písmen. Pokud se pak objeví podmínka " WHERE X = 'Pepa' ", tak se stanou dvě věci:
1. Oracle vypočítá hodnotu pro 'Pepa': HEXTORAW('7065706100')
2. Nebude pracovat se slupcem X, ale s touhle funkcí: NLSSORT("X" , 'nls_sort=''BINARY_CI''')
Výkon půjde okamžitě do kolen, přestože si datový typ plně odpovídá. Řešením je udělat si index s tou funkcí NLSSORT. Bohužel to platí i pro JOIN - nedělá se přes sloupce, ale přes ty NLSSORT funkce. Dokud je v obou tabulkách index s funkcí, tak to funguje dobře. Jakmile chybí, tak je problém.
Přidejte fakt, že case (in)sensitive je parametr session, nikoliv instance, a legrace se násobí!
Teď jsem to ověřil na Oracle 12c. Bylo to nastaveno při vytváření instance a je to vidět nastavené v V$SYSTEM_PARAMETER - nls_comp = LINGUISTIC, nls_sort = BINARY_CI.
Po přihlášení uživatele SYS se ale do session použije BINARY, BINARY.
Aplikační uživatel mi tam po loginu taky nacpe BINARY.
Takže BINARY_CI mi to bere jen když mu to explicitně nastavím triggerem na session. Nastavení instance nemá na nic vliv. Pokud si dobře pamatuji to, co nás učili, tak je to tím, že přednost má nastavení session a ta bere hodnotu z klienta. Pokud klient nemá nastaveno nic, tak se bere default (NULL), což je BINARY. Proto je potřeba to vždy v login triggeru do session vnutit.
Tak jsem to nastavil na 11g a funguje to jak ma .. nemate na klientovy nastaveny nls_comp a nls_sort variablies?
Puvodni nastaveni:
SQL> select * from NLS_INSTANCE_PARAMETERS where parameter in ('NLS_SORT','NLS_COMP');
PARAMETER VALUE
------------------------------ ----------------------------------------
NLS_SORT
NLS_COMP BINARY
SQL> alter system set nls_comp=LINGUISTIC scope=spfile;
System altered.
SQL> alter system set nls_sort = BINARY_CI scope=spfile;
System altered.
SQL> startup force;
ORACLE instance started.
Total System Global Area 835104768 bytes
Fixed Size 2257840 bytes
Variable Size 536874064 bytes
Database Buffers 289406976 bytes
Redo Buffers 6565888 bytes
Database mounted.
Database opened.
Nastaveni po zmene:
SQL> show user
USER is "SYS"
SQL> select * from NLS_INSTANCE_PARAMETERS where parameter in ('NLS_SORT','NLS_COMP');
PARAMETER VALUE
------------------------------ ----------------------------------------
NLS_SORT BINARY_CI
NLS_COMP LINGUISTIC
SQL> show parameter nls_comp
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
nls_comp string LINGUISTIC
SQL> show parameter nls_sort
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
nls_sort string BINARY_CI
Taky aplikacni user to vidi spravne:
SQL> show user
USER is "SORT"
SQL> show parameter nls_comp
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
nls_comp string LINGUISTIC
SQL> show parameter nls_sort;
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
nls_sort string BINARY_CI
SQL>
Jeste doplnim .. env variable na to nema vliv, pouze alter session, po prihlaseni opet hodnota z spfile:
SQL> hradec:~ $ env|grep NLS
NLS_SORT=BINARY
hradec:~ $ sqlplus sort
SQL*Plus: Release 11.2.0.4.0 Production on Thu May 24 07:33:33 2018
Copyright (c) 1982, 2013, Oracle. All rights reserved.
Enter password:
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
SQL> select * from NLS_INSTANCE_PARAMETERS where parameter in ('NLS_SORT','NLS_COMP');
PARAMETER VALUE
------------------------------ ----------------------------------------
NLS_SORT BINARY_CI
NLS_COMP LINGUISTIC
SQL> show parameter nls_sort
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
nls_sort string BINARY_CI
SQL> alter session set nls_sort=binary;
Session altered.
SQL> show parameter nls_sort
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
nls_sort string BINARY
SQL> exit
Disconnected from Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
hradec:~ $ sqlplus sort
SQL*Plus: Release 11.2.0.4.0 Production on Thu May 24 07:34:31 2018
Copyright (c) 1982, 2013, Oracle. All rights reserved.
Enter password:
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
SQL> show parameter nls_sort
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
nls_sort string BINARY_CI
select * from NLS_INSTANCE_PARAMETERS where parameter in ('NLS_SORT','NLS_COMP')
NLS_SORT = BINARY_CI
NLS_COMP = LINGUISTIC
show parameter nls_comp
nls_comp string BINARY
Nastavení klienta ovlivnit nemůžu. Tak jak je nastaven teď to bez login triggeru dopadne viz výše. Klient, to je úplně jiný tým lidí na jiném kontinentu. Proto je to v login triggeru, na nastavení klienta se spolehnout nemůžeme. Žil jsem v domění, že na to nespoléhá nikdy nikdo.
Ja uz jsem setkal s takovou sortou lidi a nastavenim klientu, ze se uz nedivim vubec nicemu a co nevidim na vlastnim monitoru a nemuzu primo vyzkouset ... tak tomu neverim :-))
Trosku jsem pohledal v Database Globalization Support Guide
https://docs.oracle.com/cd/E11882_01/server.112/e10729/ch3globenv.htm#NLSPG188
Tabulka priorit pro nastaveni nls je:
Table 3-1 Methods of Setting NLS Parameters and Their Priorities
Table 3-1 shows the precedence order of the different methods of setting NLS parameters. Higher priority settings override lower priority settings. For example, a default value has the lowest priority and can be overridden by any other method.
Priority Method
1 (highest)
Explicitly set in SQL functions
2
Set by an ALTER SESSION statement
3
Set as an environment variable
4
Specified in the initialization parameter file
5
Default
NLS_COMP a NLS_SORT lze nastavit vsemi zpusoby: I = Initialization Parameter File E = Environment Variable A = ALTER SESSION
Hodne stesti, Oracle forever ;-)