When using linguistic sorting parameters like BINARY_AI (accent-insensitive), Oracle transforms string comparisons using the NLSSORT function.
This transformation means that 'aé', 'ae', 'aÉ', and 'aE' would be considered equivalent for comparison purposes.
Regular indexes cannot handle these transformations, making function-based indexes essential.
Session Configuration for Accent-Insensitive Sorting:
ALTER SESSION SET NLS_SORT = BINARY_AI;
ALTER SESSION SET NLS_COMP = LINGUISTIC;
Regular Index Limitation:
DROP INDEX idx_table_nlssort_desc1;
CREATE INDEX idx_table_nlssort_desc1 ON table_nlssort ( desc1 );
ANALYZE INDEX idx_table_nlssort_desc1 COMPUTE STATISTICS;
SELECT * FROM table_nlssort WHERE desc1 = 'aÉ';
Execution Plan:
| OBJECT_NAME | OPTIONS | Filter Predicates |
+---------------+---------+----------------------------------------------------------------+
| TABLE_NLSSORT | FULL | NLSSORT(DESC1,'nls_sort=''BINARY_AI''')=HEXTORAW('0061006500') |
Oracle automatically applies the NLSSORT function to the column in the WHERE clause, but since the index is on the raw column value, it cannot be used effectively.
The HEXTORAW value represents the normalized sort key for the comparison.
Forced Index Usage (Inefficient):
SELECT /*+ index(table_nlssort idx_table_nlssort_desc1) */ * FROM table_nlssort WHERE desc1 = 'aÉ';
Execution Plan:
| OBJECT_NAME | OPTIONS | Filter Predicates |
+-------------------------+----------------+----------------------------------------------------------------+
| TABLE_NLSSORT | BY INDEX ROWID | |
| IDX_TABLE_NLSSORT_DESC1 | FULL SCAN | NLSSORT(DESC1,'nls_sort=''BINARY_AI''')=HEXTORAW('0061006500') |
Even when forced, the index requires a full scan because the transformation must be applied to every indexed value during the scan.
Proper Function-Based Index Solution:
DROP INDEX idx_table_nlssort_desc1;
CREATE INDEX idx_table_nlssort_desc1 ON table_nlssort ( NLSSORT(desc1,'nls_sort=''BINARY_AI''') );
ANALYZE INDEX idx_table_nlssort_desc1 COMPUTE STATISTICS;
SELECT * FROM table_nlssort WHERE desc1 = 'aÉ';
Execution Plan:
| OBJECT_NAME | OPTIONS | Access Predicates |
+-------------------------+----------------+----------------------------------------------------------------+
| TABLE_NLSSORT | BY INDEX ROWID | |
| IDX_TABLE_NLSSORT_DESC1 | RANGE SCAN | NLSSORT(DESC1,'nls_sort=''BINARY_AI''')=HEXTORAW('0061006500') |
With the properly configured function-based index, Oracle can efficiently perform a RANGE SCAN operation, providing optimal query performance.
The index stores the pre-computed NLSSORT values, eliminating the need for runtime transformations.