Oracle Database 12c: "Nuevas Características para Desarrolladores" (Parte II)

Por Joel Pérez & Mahir M. Quluzade (OCP)
Publicado en Octubre 2014

Reciban estimados tecnólogos Oracle un cordial saludo.
A través del presente artículo, tendremos la oportunidad de visualizar y adentrarnos un poco en algunas de las nuevas características que trajo consigo la nueva versión de base de datos ( BBDD ) “Oracle Database 12c”.

El presente artículo conforma la segunda entrega de esta serie:

“Tipos de Datos Extendidos”

En “Oracle Database 12c” se puede especificar una medida máxima de “32767 bytes” para los tipos de datos: VARCHAR2, NVARCHAR2, y columnas de tipo “RAW”. En versiones anteriores lo máximo permitido para las mencionadas columnas era solo de “4000 bytes” para datos: VARCHAR2, NVARCHAR2 y “2000 bytes” para columnas de tipo “RAW”.

  • Para ser habilitado a nivel de base de datos se necesita modificar el parámetro: MAX_STRING_SIZE a valor: EXTENDED
  • No es permitido el cambio de valor: EXTENDED a STANDARD
  • Para ambientes RAC, todas las instancias deben ser cerradas
  • Es importante recordar que los valores especificados se encuentran en bytes y no en numero de caracteres. La cantidad de caracteres que podrán ser almacenados dependerá del “Character set” utilizado en la base de datos.
  • El extender el limite de guardado de las columnas podría ocasionar “Row Chaining” entonces es aconsejable no hacer uso excesivo de la medida de las columnas en caso de no ser necesario y establecer un análisis de los objetos modificados con los asesores de acceso para posibles reordenamientos de data en caso de ser necesarios.

Procedimiento para el cambio y ejemplo:

SHUTDOWN IMMEDIATE;
STARTUP UPGRADE;
ALTER SYSTEM SET max_string_size=extended;
@?/rdbms/admin/utl32k.sql
SHUTDOWN IMMEDIATE;
STARTUP;
SQL> CREATE TABLE Mytable (
2  C1  NUMBER,
3  C2  VARCHAR2(32767),
4  C3  NVARCHAR2(16383),
5  C4  RAW(32767)
6  );

Table created.

SQL> WITH data AS
2  (SELECT 1 AS c1,
3     RPAD('X', 32767, 'X') AS c2,
4     RPAD('X', 16383, 'X') AS c3,
5     UTL_RAW.cast_to_raw(RPAD('X', 32767, 'X')) as c4
6 FROM   dual
7 UNION ALL
8 SELECT 2 AS c1,
9    LPAD('Y', 32767, 'Y') AS c2,
10   LPAD('Y', 16383, 'Y') AS c3,
11   UTL_RAW.cast_to_raw(LPAD('Y', 32767, 'Y')) as c4
12 FROM   dual
13 )
14
15 INSERT INTO MyTable SELECT c1,c2,c3,c4 FROM data;

2 rows inserted.

SQL> COMMIT;
SQL>
SQL> SELECT c1,
2     LENGTH(c2) AS LENC2,
3     LENGTH(c3) AS LENC3,
4     LENGTH(c4) AS LENC4
5 FROM  MyTable;

C1  LENC2  LENC3   LENC4
---- ----------- ----------- -----------
1    32767    16383    32767
2    32767    16383    32767

2 row selected. 

Nota: Es importante resaltar que este cambio no es reversible una vez aplicado en la base de datos.
 

 “Multiples Indices en una misma columna o lista de columnas”

Esta nueva característica esta basada en la posibilidad de crear diversos indices sobre una misma columna o lista de columnas siempre y cuando los índices a ser adicionados sean diversos respecto a los existentes en cuanto a: “unique vs non-unique”,”b*tree vs bitmap”, etc y solo uno de ellos podrá permanecer en modo visible.
Existe información en la BBDDs la cual pudiese ser mas óptimamente analizada con índices de un tipo otro. Ej: si tenemos una aplicación de tipo OLTP que trabaja durante la mayor parte del día, la mejor opción posiblemente sea tener índices de tipo “B*Tree” pero quizás la misma tabla pudiese ser objeto de análisis de tipo “Data Warehouse” en las noches. Crear y recrear índices pudiese ser muy costoso en tiempo y en recursos utilizados. Con esta nueva característica pudiésemos tener construido ambos índices y establecer el funcionamiento para alguno de ellos en un determinado punto del tiempo sin afectar la constitución física del otro.
Esta nueva característica podría ayudarnos en migraciones de aplicaciones donde se necesite una nueva estrategia de indexado de columnas siempre y cuando los nuevos índices no coincidan en características con los anteriores..
Ej. de creación de índices con características diversas para la misma columna

SQL> create index Index02 on Mytable(campo1) local invisible;

Index created.

SQL> create bitmap index Index03 on Mytable(campo1) local invisible;
Index created.

SQL> create index Index04 on Mytable(campo1) reverse invisible;
Index created.

Ej.: Para el presente caso supongamos que tenemos una tabla llamada “Mytable” el cual posee un índice único “Index01”  en la columna (campo1), y deseamos realizar el cambio de funcionamiento para que sea el índice 2 el que trabaje en modo visible. Es importante destacar que dentro de la estrategia de implantado y construcción del “Index02”, jamás se tuvo que detener el funcionamiento del “Index01”, es decir, mientras el “Index01” trabaja de forma habitual, el índice “Index02” se estaba construyendo sin afectar lo anterior. Una vez que el “Index02” estaba construido el cambio de referencia de cual índice será visible es una operación de apenas segundos.

SQL> drop index Index01 invisible;
Index dropped.

SQL> alter index Index02 visible;
Index altered.

Si establecemos el parámetro de BBDDs: “OPTIMIZER_USE_INVISIBLE_INDEXES=true” el optimizador podrá utilizar los índices invisibles para crear un plan de ejecución

SQL> create table T1 as select * from hr.employees;
Table created.

SQL> create index t1_i1 on T1 (employee_id) invisible;
Index created.

SQL> create index t1_i2 on T1 (employee_id) reverse;
Index created.

SQL> alter session set optimizer_use_invisible_indexes = true;
Session altered.

SQL> explain plan for select employee_id, last_name from T1 where employee_id=100;

Execution Plan
----------------------------------------------------------
Plan hash value: 2242215931
------------------------------------------------------------------
| Id  | Operation                           | Name   |
------------------------------------------------------------------
| 0   | SELECT STATEMENT      |        |
| 1   | TABLE ACCESS BY INDEX ROWID BATCHED| T1 |
|* 2  | INDEX RANGE SCAN | T1_I1 |
------------------------------------------------------------------


 
“Capacidades mejoradas para operaciones “DDL” en linea”

Esta nueva característica nos permite llevar a cabo las siguientes tareas de tipo DDL, sin interrupciones de mantenimiento de “Schema” al llevar a cabo operaciones de tipo DML, estableciendo la clausula “ONLINE”.

  • Drop Index
  • Drop Constraint
  • Alter Index Unusable
  • Set Column Unused

Esta nueva capacidad ofrece ventajas para mayor versatilidad y flexibilidad de migraciones y desarrollo de aplicaciones.
La operación “Drop Index” “ONLINE” es soportada para índices particionados y no particionados

SQL> DROP INDEX schema.index ONLINE;

La operacion “Drop Constraint” “ONLINE” permite remover un “Constraint” de integridad de la base de datos siempre y cuando no lleve a cabo para los siguientes casos:

  • No se puede remover un “Constraint” con opción “CASCADE”
  • No se puede eliminar un “Constraint” de referencia

SQL> ALTER TABLE hr.employees
2 DROP CONSTRAINT emp_email_uk ONLINE;

“Establecimiento de estatus ‘UNUSABLE’ para indices”
Característica para designar estado “UNUSABLE” a: indices, particiones de Indices & Sub-particiones de índices.
El estado “UNUSABLE” hace posible la liberación inmediata ocupada por el respecto segmento que fue objeto del cambio mencionado.
Si se requiriese el uso nuevamente el segmento en estatus “UNUSABLE” se deberá realizar una operación de: “Rebuilt” o borrado y recreación del índice.
Nota: la clausula “UNUSABLE” no puede ser utilizada por indexes pertenecientes a tablas temporales.
Es permitido utilizar la clausula “ONLINE” para evitar la interrupción de operaciones “DML” durante la ejecución de los procesos mencionados.

SQL> ALTER INDEX hr.i_emp_ix UNUSABLE ONLINE;
Index altered.

SQL> SELECT status FROM user_indexes
2   WHERE table_name='EMP';

INDEX_NAME       STATUS
------------------------ ------------
I_EMP_IX              UNUSABLE

 
“Establecimiento de estado UNUSED para columnas”
A través de la clausula “Set UNUSED” podemos liberar de forma automática el espacio perteneciente a una columna de una tabla y el establecimiento de su no disposición como columna de la tabla. Es el primer paso que se realiza para el proceso de remoción de una columna y liberación de espacio. Al igual que las clausulas anteriores si utilizamos la clausula “ONLINE” las operaciones de tipo “DML” podrán llevarse a cabo sin interrupción.

SQL> CREATE TABLE emp (ename VARCHAR2(20), id NUMBER);
SQL> INSERT INTO emp VALUES('Tim',4);
SQL> SELECT * FROM emp;
SQL> ALTER TABLE emp SET UNUSED (ename) ONLINE;
SQL> DESC emp;
Name           Null? Type
---------------- ------  ----------------------------
ID                          NUMBER



“Clausulas de limitación para ’SQL Row’”

En “Oracle Database 12c” los mecanismos para limitar cantidad y modo de extracción de registros han tenido una mejora significativa, proveyéndonos de nuevas clausulas.

  • Podemos especificar la cantidad de registros a ser retornados utilizando las palabras claves: “FETCH”,”FIRST”,”NEXT”
  • Podemos especificar la cantidad de registros a ser retornados con la clausula “PERCENT”
  • Con la clausula “OFFSET” podemos especificar la cantidad de registros deseados a partir del primer registro de un set de resultados complemento a la data que ya se ha obtenido.

Las consultas que generalmente utilizan este tipo de clausulas son conocidas como: “Top-N Queries”. Veamos un ejemplo práctico de esta característica:

SQL> drop table nums purge;

SQL> create table nums as
2  select level as num from dual
3  connect by level <= 100;

Table created.

SQL> select count(1) as cnt from nums;

CNT
------------
100

SQL> select num from  nums
2  order by 1 desc
3  fetch first 10 rows only;

NUM
------------
100
99
98
97
96
95
94
93
92
91

SQL> select num from nums
2  order by 1
3  fetch first 12 percent rows only;

NUM
------------
1
2
3
4
5
6
7
8
9
10
11
12

SQL> select num from nums
2  order by 1
3  offset 4 rows fetch next 6 rows only;

NUM
------------
5
6
7
8
9
10

SQL> select num from nums
2  order by 1
3  offset 2 rows fetch next 15 percent rows only;

NUM
------------
3
4
5
6
7
8
9
10
11
12
13
14
15
16

SQL> insert into nums select *  from nums;

10 rows inserted

SQL> commit;

SQL> select count(1) as cnt from nums;

CNT
----------
200

SQL> select num from   nums
2  order by 1 desc
3  fetch first 7 rows with ties;

NUM
------------
100
100
99
99
98
98
97
97



Esperando una vez más que este material sea de provecho significativo para ustedes como lector, nos despedimos hasta la próxima.
Saludos. 


Joel es un experto DBA con más de 12 años de experiencia, especializado en bases de datos con especial énfasis en la soluciones de alta disponibilidad (RAC, Data Guard, y otras). Es un conferencista habitual en eventos de Oracle como: OTN LAD TOUR y otros. Consultor Internacional con trabajos en más de 20 países alrededor del mundo. Fue el primer latinoamericano en ser nombrado "Experto OTN" en el año 2003, Oracle ACE año 2004 y actualmente Oracle ACE Director.

Mahir es un Senior DBA con mas de 10 anos de experiencia en bases de datos Oracle con especial foco en "High Availability" & "Disaster Recovery Solutions (RAC, Data Guard, RMAN,…)". Mahir actualmente trabaja en el "Central Bank of the Republic of Azerbaijan". El es OCP DBA. Mahir es frecuente orador en el "Azerbaijan Oracle User Group (AZEROUG)".