Oracle Corporation introdujo en la versión 8 de su base de datos los índices de tipo reversed. De acuerdo a la documentación estos índices son la mejor configuración para ambientes con Oracle Parallel Server o bien con alta transaccionalidad. El concepto en sí es muy interesante y consiste en invertir cada uno de los bytes de las columnas indexadas (salvo el tipo ROWID), de este modo si se tiene un índice numérico que se basa en una secuencia las nuevas filas no se insertarán en un mismo bloque sino en distintos bloques.
¿Cómo es que esto funciona? Tomemos como ejemplo una aplicación con una alta transaccionalidad OLTP de modo que en un microsegundo se generan 5 nuevas filas, las filas serán insertadas en una tabla con una única columna indexada y cuyo valor es generado por una secuencia. De éste modo tenemos en dicho microsegundo que insertar 5 columnas con las siguientes secuencias
4583
4584
4585
4586
4587
En total tenemos 5 transacciones, cada una pertenece a una sesión distinta. Los índices de llaves invertidas -reversed key indexes- convertirán las secuencias en
3854
4854
5854
6854
7854
Las filas serán insertadas en los bloques de la tabla que estén disponibles de acuerdo al órden del SCN asignado a cada transacción.
Según la documentación de soporte los índices reversed key son muy eficientes en cuanto a desempeño se refiere porque cuando en un ambiente OLTP intenso las modificaciones a los índices se enfocan en un pequeño conjunto de bloques de hojas. Invirtiendo los índices del índice permite que las inserciones se distribuyan en todas las llaves hoja en el índice. Los índices invertidos previenen que las sentencias ejecuten una operación de index range scan debido a que las llaves léxicamente adyacentes no se almacenan físicamente una junto a la otra. Los índices invertidos también pueden utilizarsee en situaciones donde los usuarios insertan ascendentemente valores y eliminan valores menores de la tabla, ayudando por tanto con la prevención de índices dispersos. (Traducción literal).
¿Será ésto cierto?
Las estadísticas para los índices que creamos son los siguientes, nótese la enorme diferencia en el clustering factor. El clustering factor es una estadística utilizada por el CBO para estimar cuántas lecturas a bloques distintos tendrán que hacerse en el caso de lecturas tipo FTS o bien range scan con alta cardinalidad.
TABLE INDEX CF BLEVEL LBLOCKS DKEYS LBPK DBPK NUM_ROWS
----------------------------------------------------------------------------
LARGE LARGE_ID 2186 1 1099 999999 1 1 999999
LARGE1 LARGE1_UNIQUEID 999988 1 1099 999999 1 1 999999
Resulta claro que el índice de llaves invertidas tenga un clustering factor inmensamente más alto que un índice normal, y eso que la tabla tiene casi 1 millón de filas.
Dada la sentencia
update (large||large1) set subobject_name='UPDATED' where uniqueid between 555555 and 888888;
tenemos los planes y los tiempos de ejecución
ÍNDICE BTREE
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | 333K| 2278K| 938 (1)| 00:00:14 |
| 1 | UPDATE | LARGE | | | | |
|* 2 | TABLE ACCESS FULL| LARGE | 333K| 2278K| 938 (1)| 00:00:14 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
—————————————————
2 – filter(“UNIQUEID”>=555555 AND “UNIQUEID”<=888888)
Elapsed: 00:00:31.70
ÍNDICE CON LLAVES INVERTIDAS
-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | 333K| 2278K| 944 (1)| 00:00:14 |
| 1 | UPDATE | LARGE1 | | | | |
|* 2 | TABLE ACCESS FULL| LARGE1 | 333K| 2278K| 944 (1)| 00:00:14 |
-----------------------------------------------------------------------------
Predicate Information (identified by operation id):
—————————————————
2 – filter(“UNIQUEID”>=555555 AND “UNIQUEID”<=888888)
Elapsed: 00:00:31.49
Para el caso de modificaciones masivas tenemos casi lo mismo en cuanto a costo y tiempos de ejecución, así que el supuesto beneficio de los índices de llaves invertidas sobre los índices btree es prácticamente inexistente (omitiendo las limitaciones por diseño de un índice invertido).
Ahora vamos a analizar para el caso de acceso a las tablas donde la sentencia pide una cardinalidad reducida y utilizando el índice sobre uniqueid.
ÍNDICE BTREE
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | 42 | 294 | 3 (0)| 00:00:01 |
| 1 | UPDATE | LARGE | | | | |
|* 2 | INDEX RANGE SCAN| LARGE_ID | 42 | 294 | 2 (0)| 00:00:01 |
------------------------------------------------------------------------------
Predicate Information (identified by operation id):
—————————————————
2 – access(“UNIQUEID”>=555510 AND “UNIQUEID”<=555550)
Elapsed: 00:00:00.02
ÍNDICE CON LLAVES INVERTIDAS
-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | 42 | 294 | 943 (1)| 00:00:14 |
| 1 | UPDATE | LARGE1 | | | | |
|* 2 | TABLE ACCESS FULL| LARGE1 | 42 | 294 | 943 (1)| 00:00:14 |
-----------------------------------------------------------------------------
Predicate Information (identified by operation id):
—————————————————
2 – filter(“UNIQUEID”>=555510 AND “UNIQUEID”<=555550)
Elapsed: 00:00:00.11
La ejecución de la sentencia utilizando el índice btree tiene un tiempo de ejecución del 18% de lo que tarda la misma sentencia que utiliza el índice con llaves invertidas … ¿dónde queda entonces la superioridad del índice con llaves invertidas aún en la misma situación donde la documentación del índice invertido lo supone muy superior?
He visto en incontables ocasiones ambientes productivos con “nuevas características” tecnológicas cuya razón de ser obedece a que los administradores/desarrolladores tomaron un curso o bien leyeron en internet sobre supuestos beneficios, y decidieron “proactivamente” implantarlos en sus ambientes (heme aquí insistiendo en la importancia de hacer pruebas y de dudar de cualquier cosa que aparezca en internet o bien en la documentación).
Concluimos que hay que tener mucho cuidado con lo que se lee en internet o en cualquier documentación, es muy fácil decir cosas cuando no se presenta una demostración. ¿No es en las observaciones, inducción, hipótesis, experimentación, demostración y teoría en lo que el método científico se basa?