Buscar este blog

martes, 17 de octubre de 2017

Instalacion Oracle 11.2.0.4 Oracle Linux 6.4

Descargamos los binarios necesario para la instalación


#11.2.0.4
unzip p13390677_112040_Linux-x86-64_1of7.zip
unzip p13390677_112040_Linux-x86-64_2of7.zip
The "/etc/hosts" file must contain a fully qualified name for the server.
<IP-address>  <fully-qualified-machine-name>  <machine-name>
For example.
127.0.0.1       localhost       localhost.localdomain

192.168.203.14  srvt03gdb02.sigfe.local srvt03gdb02

Oracle Installation Prerequisites

Antes debemos crear un repositorio para yum, local o remoto
para esto debemos ir a: /etc/yum.repos.d/ y mover lo siguiente desde
otro servidor ya configurado:
[oracle@srvt01mid01 etc]$ scp -R yum.repos.d/ root@192.168.203.14:/etc
[oracle@srvt01mid01 yum.repos.d]$ ls -ltr total 12 -rw-r--r-- 1 root root 91 Aug 1 2014 local.repo -rw-r--r-- 1 root root 115 Aug 1 2014 local-updates.repo -rw-r--r-- 1 root root 561 Aug 1 2014 rhel-debuginfo.repo
En nuestro servidor con el nuevo repositorio:
[root@srvt03gdb02 yum.repos.d]# find / -name *GPG* /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-beta /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-legacy-former /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-legacy-release /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-legacy-rhx
[root@srvt03gdb02 yum.repos.d]# rpm --import
/etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release [root@srvt03gdb02 yum.repos.d]# rpm --import
/etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-beta
[root@srvt03gdb02 yum.repos.d]# yum update
Estamos listos para instalar cualquier RPM necesario para nuestro motor Oracle.
Ejemplo:
[root@srvt03gdb02 yum.repos.d]# yum install unzip, sysstat.x86_64
[root@srvt03gdb02 yum.repos.d]# yum install vncserver, xterm, make.x86_64
[root@srvt03gdb02 oracle]# yum install libaio.x86_64 libaio.i686

Necesitamos aumentar el area temporal /tmp:
[root@srvt03gdb02 ~]# pvs PV VG Fmt Attr PSize PFree /dev/sda2 gso lvm2 a-- 149.85g 134.60g /dev/sdb1 vgoracle lvm2 a-- 166.66g 66.66g /dev/sdb2 vgoracle lvm2 a-- 166.66g 166.66g /dev/sdb3 vgoracle lvm2 a-- 166.67g 166.67g

[root@srvt03gdb02 ~]#  lvresize -r -L +2G /dev/mapper/gso-tmp
  Extending logical volume tmp to 3.00 GiB
  Logical volume tmp successfully resized
resize2fs 1.41.12 (17-May-2010)
Filesystem at /dev/mapper/gso-tmp is mounted on /tmp; on-line resizing required
old desc_blocks = 1, new_desc_blocks = 1
Performing an on-line resize of /dev/mapper/gso-tmp to 786432 (4k) blocks.
The filesystem on /dev/mapper/gso-tmp is now 786432 blocks long.


[root@srvt03gdb02 ~]# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/gso-raiz  2.0G  266M  1.7G  14% /
tmpfs                 5.9G     0  5.9G   0% /dev/shm
/dev/sda1             146M   43M   96M  31% /boot
/dev/mapper/gso-home  248M   11M  226M   5% /home
/dev/mapper/gso-opt   2.0G   69M  1.9G   4% /opt
/dev/mapper/gso-tmp   3.0G  130M  2.7G   5% /tmp
/dev/mapper/gso-usr   4.0G 1006M  2.8G  27% /usr
/dev/mapper/gso-var   2.0G  182M  1.7G  10% /var
/dev/mapper/vgoracle-vg01
                       99G  8.1G   86G   9% /u01
Configuramos acceso remoto para correr ./runInstaller
[oracle@srvt03gdb02 ~]$ vncserver You will require a password to access your desktops. Password: Verify: xauth: creating new authority file /home/oracle/.Xauthority New 'srvt03gdb02:1 (oracle)' desktop is srvt03gdb02:1 Creating default startup script /home/oracle/.vnc/xstartup Starting applications specified in /home/oracle/.vnc/xstartup Log file is /home/oracle/.vnc/srvt03gdb02:1.log
Paso siguiente descomprimimos los binarios de Oracle:
[oracle@srvt03gdb02 oracle]$ unzip linux.x64_11gR2_database_1of2.zip
[oracle@srvt03gdb02 oracle]$ unzip linux.x64_11gR2_database_2of2.zip
[oracle@srvt03gdb02 database]$
Accedemos via VNC al servidor para levantar entorno grafico:

Manejo de excepciones en PL/SQL (excepciones predefinidas)

Los errores que se producen durante la ejecución de un bloque de código PL/SQL pueden ser manejados a gusto del programador, es decir, si durante la ejecución de una sentencia PLSQL se produce un error, podemos hacer que el programa realice unas acciones u otras dependiendo del tipo de error que se haya generado, esto es algo parecido a lo que se puede hacer cuando programamos en C++ o Java. Para conseguir esto debemos añadir dentro del bloque de código PL/SQL una sección para tratamiento de las excepciones.

Existen dos tipos de excepciones:

- Excepciones predefinidas
- Excepciones definidas por el usuario.

En este artículo voy a hablar sólo de las excepciones predefinidas.

PL/SQL proporciona un gran número de excepciones predefinidas que permiten controlar las condiciones de error más habituales. Las excepciones predefinidas no necesitan ser declaradas y son las siguientes:

DUP_VAL_ON_INDEX - Se produce cuando se intenta almacenar un valor ya existente en una columna que tiene restricción de índice único.

TIMEOUT_ON_RESOURCE - Se excedió el tiempo máximo de espera por un recurso en Oracle.

NOT_LOGGED_ON - El programa efectuó una llamada a Oracle sin estar conectado.

LOGIN_DENIED - El login o la contraseña utilizados para entrar en Oracle son inválidos.

NO_DATA_FOUND - Una sentencia SELECT INTO no devolvió ningún registro.

TOO_MANY_ROWS - Una sentencia SELECT INTO devolvió más de un registro.

ZERO_DIVIDE - Se ha ejecutado una división donde el divisor valía cero.

STORAGE_ERROR - Si no se dispone de más memoria o la memoria esta dañada.

PROGRAM_ERROR - Ocurrió un problema interno al ejecutar el código PL/SQL.

INVALID_NUMBER - Cuando falla la conversión de una cadena de caracteres hacia un número porque la cadena no representa un número válido.

VALUE_ERROR - Ocurrió un error aritmético, de conversión o truncamiento. Por ejemplo, esto sucede cuando se intenta dar un valor muy grande a una variable que no soporta dicho tamaño.

ROWTYPE_MISMATCH - Los elementos de una asignación (el valor a asignar y la variable que lo contendrá) son de tipos incompatibles. También se presenta este error cuando un parámetro pasado a un subprograma no es del tipo esperado.

SYS_INVALID_ROWID - Falla la conversión de una cadena de caracteres hacia un tipo rowid porque la cadena no representa un número.

INVALID_CURSOR - Se efectuó una operación no válida sobre un cursor. Suele ocurrir cuando un cursor no está abierto y se ejecuta una sentencia para cerrar dicho cursor.

CURSOR_ALREADY_OPEN - Cuando se intenta abrir un cursor que ya estaba abierto. Hay que recordar que un cursor de tipo FOR se abre automáticamente por lo que no se debe ejecutar la sentencia OPEN.

ACCESS_INTO_NULL - Se intentó asignar un valor a los atributos de un objeto no inicializado.

COLLECTION_IS_NULL - Se intentó asignar un valor a una tabla anidada aún no inicializada.

SELF_IS_NULL - El parámetro SELF (el primero que es pasado a un método MEMBER) es nulo.

OTHERS - Cualquier otro tipo de error que pueda producirse. Cuando se utiliza la excepción OTHERS, cualquier excepción que no se haya tratado anteriormente se procesará según la secuencia de instrucciones incluida dentro de la sección OTHERS. OTHERS debe ser la última excepción tratada dentro de la sección dedicada al tratamiento de excepciones.

La sintaxis de una sección para tratamiento de excepciones es como sigue:

   BEGIN
     [Secuencia de sentencias]
     EXCEPTION
     WHEN [nombre de la excepción 1] THEN
       [Sentencias para tratar la excepción 1]
     .................................................
     WHEN [nombre de la excepción n] THEN
       [Sentencias para tratar la excepción n]
     WHEN OTHERS THEN
       [Sentencias para tratar el resto de las excepciónes]
     END;

En el siguiente ejemplo se utilizan las excepciones predefinidas NO_DATA_FOUND, TOO_MANY_ROWS y OTHERS:

   DECLARE
     vprecio inventario.precio%TYPE;
   BEGIN
     [Otras sentencias]
     BEGIN
       SELECT precio FROM inventario
       WHERE cantidad = 100
       INTO vprecio;
       EXCEPTION
       WHEN NO_DATA_FOUND THEN
         DBMS_OUTPUT.PUT_LINE("No hay ningún artículo.");
       WHEN TOO_MANY_ROWS THEN
         DBMS_OUTPUT.PUT_LINE("Hay más de un artículo.");
       WHEN OTHERS THEN
         DBMS_OUTPUT.PUT_LINE("Error, abortando ejecución.");
         RAISE;
     END;
     [Otras sentencias]
   END;

En este ejemplo si la sentencia SELECT INTO fallase por no devolver ningún registro o por devolver más de uno, se mandaría un mensaje de error a la pantalla pero la ejecución del programa continuaría; por contra, para cualquier otro error, aunque también se mandaría un mensaje de error a la pantalla, la ejecución del programa se abortaría (comando RAISE).

viernes, 30 de diciembre de 2016

Traza y Diagnostico Oracle RAC

DOC ID : Diagnosability for Oracle Clusterware (CRS or Grid Infrastructure) Component and Resource (Doc ID 357808.1)


Trazas y Diagnosticos de LOG en Oracle RAC.

$CRS_HOME/log , Para el diagnostico del Clusterware contiene los siguientes archivos..

ClusterWare Alert ==>  nodo1rac.log

Client ==> Para aplicaciones OCR

RACG ==> /racg/dump  Logfiles para aplicaciones de los nodos incluidas las VIP ONSCrsd crs/log

CSSD /css/log
Evmd /evm/log

Para revisar configuracion de niveles de LOG

[grid@lpprpaxbd01]$ crsctl get log res ora.cdr.db
Get Resource ora.cdr.db Log Level: 1

Para ver los modulos del cluster:










Para revisar niveles de log por module:
CSS: Cluster Synchronozation Services












CRS: Cluster Ready Services:


























Las definiciones para los niveles de Log:

level 0 = turn off
level 2 = default
level 3 = verbose
level 4 = super verbose


Ahora veremos como aumentar el nivel de log para los componentes mas criticos de oracle rac clusterware, escogeremos un servicio critico como CSS para re configurar el nivel de log, para realizar un trace sobre la informacion registrada en algun evento de nivel critico sobre el recurso de cluster CSS.

 CSS:  Cluster Synchronization Services














Ademas Oracle cuenta con una herramienta de diagnostico para recopilar información del Clusterware para enviar a Oracle posterior a la creación de un Service Request CR.

diagcollecton.sh es un script del CRS que recolecta los logs del CRS del nodo local , es un wrapper sobre el perl diagcollection.pl

Obtiene información sobre:
• Cluster Synchronization Services (CSS)
• Event Manager (EVM)
• Cluster Ready Services (CRS) daemons.

Este log suele ser solicitado por soporte Oracle , El tamaño es bastante grande ( del orden de 1,1 Gb ) 
La forma de uso es muy sencilla,solamente hay que buscarlo bajo el arbol de directorios del GRID.

Linux/UNIX 10gR2/11gR1

1. Execute the following as root user:
# script /tmp/diag.log
# id
# env
# cd <temp-directory-with-plenty-free-space>
# export OCH=<CRS_HOME>
# export ORACLE_HOME=<DB_HOME>
# export HOSTNAME=<host>
# $OCH/bin/diagcollection.pl -crshome=$OCH --collect
# exit

The following .gz files will be generated in the current directory and need to be uploaded along with /tmp/diag.log:   
crsData_<hostname>.tar.gz,
ocrData_<hostname>.tar.gz,
oraData_<hostname>.tar.gz,
coreData_<hostname>.tar.gz (only --core option specified)

miércoles, 28 de diciembre de 2016

Como multiplexar controfile en +ASM

1.- Vemos que el controlfile se encuentra solo en un DIKGROUP del +ASM.









2.- Bajamos la base de datos con srvctl, para el caso de grid infraestructura.

srvctl stop database -a cdr

3.- Nos conectamos con rman, para levantar solo la SGA de la instancia, esto solo si la base de datos es standalone, de lo contrario en Oracle RAC, se debe hacer lo siguiente: srvctl start database -d cdr -o nomount.










4.- Restauramos controlfile desde el origen al destino nuevo (multiplexado).










5.- revisamos en el +ASM, que se halla creado el controfile.











6.- Ahora realizmos alter system set control, abrimos la base de datos con force, y validamos en la vista v$controlfile los control multiplexados.

















lunes, 26 de septiembre de 2016

RE-CREAR TBS UNDOTBS ORACLE RAC

COMO RE-CREAR TABLESPACE UNDOTBS EN ORACLE RAC de 4 nodos:

EL UNDO UNDOTBS4 esta mal construido, se debe re crear con los valores correctos,
este undo pertenece a la instancia 4 del RAC, para esto se debe trabajar en el nodo
4.

AUTOEXTENT de 1024M
MAXSIZE    de 20480M
SIZE       de 1024M

1.- Creamos un UNDO de PASO:
Nos conectamos al nodo 4 del RAC.

CREATE UNDO TABLESPACE UNDOTBS5 DATAFILE '+CROSS_DATA' SIZE 1024M
REUSE AUTOEXTEND ON NEXT 1024M MAXSIZE 20480M;

ALTER system SET undo_tablespace=UNDOTBS5 sid='cross4';


2.- Revisamos si tenemos segmentos de UNDO:

 SELECT a.name,b.status , d.username , d.sid , d.serial#
   FROM v$rollname a,v$rollstat b, v$transaction c , v$session d
   WHERE a.usn = b.usn
   AND a.usn = c.xidusn
   AND c.ses_addr = d.saddr
   AND a.name IN (
   SELECT segment_name
   FROM dba_segments
   WHERE tablespace_name = 'UNDOTBS4'
   );


select owner, segment_name, tablespace_name, status from dba_rollback_segs where tablespace_name='UNDOTBS4' and status='ONLINE';

 alter rollback segment "_SYSSMU31_2521593980$" offline;
 alter rollback segment "_SYSSMU32_1804532818$" offline;       
 alter rollback segment "_SYSSMU33_3611631434$" offline;                      
 alter rollback segment "_SYSSMU34_1975830645$" offline;                      
 alter rollback segment "_SYSSMU35_1514068533$" offline;                      
 alter rollback segment "_SYSSMU36_412588268$ " offline;                      
 alter rollback segment "_SYSSMU37_1727375658$" offline;                      
 alter rollback segment "_SYSSMU38_4056056697$" offline;                      
 alter rollback segment "_SYSSMU39_1922814765$" offline;                      
 alter rollback segment "_SYSSMU40_1873340872$" offline;


REFERENCIA: http://neeraj-dba.blogspot.cl/2011/05/how-to-drop-undo-tablespace.html


3.- Borramos el UNDOTBS4 de paso:

DROP tablespace UNDOTBS4 including contents and datafiles;


4.- Ahora podemos re crear el UNDOTBS4 con la correccion de estructura:


CREATE UNDO TABLESPACE UNDOTBS4 DATAFILE '+CROSS_DATA' SIZE 1024M
REUSE AUTOEXTEND ON NEXT 1024M MAXSIZE 20480M;

ALTER system SET undo_tablespace=UNDOTBS4 sid='cross4';



5.- Ahora borramos el UNDO de PASO. UNDOTBS5


DROP tablespace UNDOTBS5 including contents and datafiles;



jueves, 8 de septiembre de 2016

MIGRACION BLOB


MIGRACION BLOB

Uso de Redefinition:

How to Re-Organize a Table Online (Doc ID 177407.1)

PROPOSITO:

Se deben mover segmentos LOBs desde un DISKGROUP (+MRO_DATA) conformado por discos de 40k,
a un nuevo diskgroup (+MRO_BLOB) con discos SATA VMAX 20k, este diskgroup por 5 discos de 200GB.


La tabla comprometida COR_BLOB_DATA con su campo de tipo BLOB (BLOB_DATA), esta contiene 700GB aprox en segmentos 
de tipo LOB (), esta prueba se realiza en el ambiente MRO rac stress, servidores lstrmrobd01 y lstrmrobd02.



Restrictions
------------
The table to be re-organized:
  * Must have a primary key (restriction should have been lifted in 9.2.0.5. 
    It is possible that there is still a problem with this.)
  * Cannot have User-defined data types
  * Cannot have FILE or LONG columns
  * Cannot be clustered
  * Cannot be in the SYS or SYSTEM schema
  * Cannot have materialized view logs and/or 
                materialized views defined on them
  * Cannot be an horizontal subsetting of data
  * Must be re-organized within the same schema
  * Looses its snapshot logs
  * Can get new columns as part of the re-organization, but the
    new columns must be declared NULL until the re-organization 
    is complete

Proceso
-------

   ------ ------ 5' Table COR_BLOB_DATA_ITERIM se convierte en COR_BLOB_DATA  
   |                       y vice-versa      |
    
   1                                            2
 Source Table           3              Create interim Table 
COR_BLOB_DATA     ---> Start redefinition --->      COR_BLOB_DATA_ITERIM 
               3' data Source to Target   ^      ^          
   ^                                     /       |
   |                                    /        |
   |                                   /         4
   |                                  /    Create constraints 
                                     /     Create indexes
   3''                              /      Create triggers
DML on source table                /
updates/deletes/inserts         5 /Finish redefinition
stored into MLOG$_COR_BLOB_DATA      ------



Step 1: Verificar que la tabla puede ser redefinida online.

Step 2: Crear una tabla de paso vacia con la estructura de la tabla original, aqui
        se puede modificar alguna caracterista en su estructura, por ejemplo advance compress.

Step 3: Comienzo del proceso para redefinir la tabla: 
        dbms_redefinition_start

        Cuando comienza el proceso de redefiniton automaticamente hace esto: 
         
         -> inserts all rows from the source table into the 
            interim table 

         -> crea una tabla snapshot MLOG$_XXX y snapshot log
            almacena los cambios DML temporalmente desde el comienzo al final
            del proceso de redefiniton.


Step 4: Se crean las dependencias de la tabla (constraint, trigger,etc)

Step 5: Fin del proceso de redefinition de la tabla
        dbms_redefinition_finish

        Al terminar el proceso finish_redef_table automaticamente hace esto: 

         -> Aplica todos los cambios DML almacenados en la tabla snapshot dentro de la tabla de paso.

         -> intercambio de nombes entre las 2 tablas, la tabla de paso se
            convierte en la de origen y viceversa.

        NOTA: Hay que tener en cuenta los nombres de constraint e indices no tienen el mismo nombre que antes

Step 6: Borramos la tabla de paso.

Step 7: Para RDBMS version 9.2 hacia delante, las constraints e indices puede ser 
        renombrados con ALTER TABLE ... RENAME CONSTRAINT ... 
   

Para esta actividad:
---------------------------
--> La estructura de la tabla:

    SQL> desc EXMRO.COR_BLOB_DATA
    Name                                  Null?    Type
    ------------------------------------- -------- ---------------
     BLOB_DB_ID                                                    NOT NULL NUMBER(10)
     BLOB_ID                                                           NOT NULL NUMBER(10)
     BLOB_DATA                                                      BLOB
     RSTAT_CD                                                         NUMBER(3)
     CREATION_DT                                                  DATE
     REVISION_DT                                                   DATE
     REVISION_DB_ID                                             NUMBER(10)
     REVISION_USER                                              VARCHAR2(30)
     ORIG_CREATION_DT                                       DATE

--> la tabla contiene 1.031.453 filas antes de la re-organization:

    SQL> select count(*) from EXMRO.COR_BLOB_DATA;

      COUNT(*)
    ----------
        1.031.453
   ----------------------------------------------------------------------------------
1. Vemos si la tabla puede ser redefinida online re-organization 
   -----------------------------------------------------------------------------------
   SQL> connect sys/xxx as sysdba
   Connected.

   SQL> grant execute on dbms_redefinition to test;
   Grant succeeded.

   SQL> connect test/test
   Connected.

   SQL> execute DBMS_REDEFINITION.CAN_REDEF_TABLE('EXMRO','COR_BLOB_DATA_ITERIM');
   PL/SQL procedure successfully completed.


   ------------------------------------------------------------
2. Creamos la tabla de paso con su nueva estructura, apuntando 
   al nuevo tablespace del nuevo diskgroup
   ------------------------------------------------------------
  
   CREATE TABLE EXMRO.COR_BLOB_DATA_ITERIM
   (
     BLOB_DB_ID        NUMBER(10)                  NOT NULL,
     BLOB_ID           NUMBER(10)                  NOT NULL,
     BLOB_DATA         BLOB,
     RSTAT_CD          NUMBER(3),
     CREATION_DT       DATE,
     REVISION_DT       DATE,
     REVISION_DB_ID    NUMBER(10),
     REVISION_USER     VARCHAR2(30 BYTE),
     ORIG_CREATION_DT  DATE                        DEFAULT SYSDATE
   )
   LOB (BLOB_DATA) STORE AS (
     TABLESPACE  EXMRO_BLOB_TEST
     ENABLE      STORAGE IN ROW
     CHUNK       8192
     RETENTION
     NOCACHE
     LOGGING
         STORAGE    (
                     INITIAL          256K
                     NEXT             256K
                     MINEXTENTS       1
                     MAXEXTENTS       UNLIMITED
                     PCTINCREASE      0
                     BUFFER_POOL      DEFAULT
                     FLASH_CACHE      DEFAULT
                     CELL_FLASH_CACHE DEFAULT
                    ))
   TABLESPACE EXMRO
   RESULT_CACHE (MODE DEFAULT)
   PCTUSED    0
   PCTFREE    10
   INITRANS   1
   MAXTRANS   255
   STORAGE    (
               INITIAL          256K
               NEXT             256K
               MAXSIZE          UNLIMITED
               MINEXTENTS       1
               MAXEXTENTS       UNLIMITED
               PCTINCREASE      0
               BUFFER_POOL      DEFAULT
               FLASH_CACHE      DEFAULT
               CELL_FLASH_CACHE DEFAULT
              )
   LOGGING 
   NOCOMPRESS 
   NOCACHE
   NOPARALLEL
   MONITORING;

   ----------------------------------------------------
3. Comienzo proceso de re-organization 
   ----------------------------------------------------

cd /home/oracle/dbacore/bca/lob

nohup ./3.start.sh &

[oracle@lstrmrobd01 lob]$ more 3.start.sh
#!/bin/sh
sqlplus / as sysdba << EOF > ./output.log
set timi on
spool redef.log

BEGIN
DBMS_REDEFINITION.START_REDEF_TABLE
 (uname=>'EXMRO',
 orig_table=>'COR_BLOB_DATA',
 int_table=>'COR_BLOB_DATA_ITERIM',
 options_flag=>DBMS_REDEFINITION.CONS_USE_ROWID);
end;
/
EOF

Si se realiza con un usuario creado para la actividad debe tener los siguientes GRANT:

     * CREATE ANY TABLE 
     * ALTER ANY TABLE 
     * DROP ANY TABLE 
     * LOCK ANY TABLE 
     * SELECT ANY TABLE
     * CREATE ANY INDEX
     * CREATE ANY TRIGGER 


   SQL> select sql_text from v$sqlarea where sql_text like '%ITERIM%';


 Esto hace el redefinition cuando se ejecuta el start_redefinition:


INSERT /*+ BYPASS_RECURSIVE_CHECK APPEND SKIP_UNQ_UNUSABLE_IDX */ INTO "EXMRO"."COR_BLOB_DATA_ITERIM"(M_ROW$$,"BLOB_DB_ID","BLOB_ID","BLOB_DATA","RSTAT_CD","CREATION_DT","REVISION_DT","REVISION_DB_ID","REVISION_USER",
"ORIG_CREATION_DT") SELECT "COR_BLOB_DATA"."ROWID","COR_BLOB_DATA"."BLOB_DB_ID","COR_BLOB_DATA"."BLOB_ID","COR_BLOB_DATA".
"BLOB_DATA","COR_BLOB_DATA"."RSTAT_CD","COR_BLOB_DATA"."CREATION_DT","COR_BLOB_DATA"."REVISION_DT","COR_BLOB_DATA"."
REVISION_DB_ID","COR_BLOB_DATA"."REVISION_USER","COR_BLOB_DATA"."ORIG_CREATION_DT" FROM "EXMRO".
"COR_BLOB_DATA" "COR_BLOB_DATA"


El proceso de redefinition utiliza HINT no documentado (BYPASS_RECURSIVE_CHECK) para forzar el uso del CBO de un EXPLAIN_PLAN correcto, 
que no admita otro camino para el proceso de INSERT y SKIP_UNQ_UNUSABLE_IDX (le dice al optimizador que se salte los indices inutilizables)


   SQL> select master,log_table from dba_mview_logs;

   MASTER                         LOG_TABLE
   ------------------------------ ------------------------------
   COR_BLOB_DATA                  MLOG$_COR_BLOB_DATA


   SQL> select mview_name,container_name, build_mode from dba_mviews;

 MVIEW_NAME                     CONTAINER_NAME                 BUILD_MOD
 ------------------------------ ------------------------------ ---------

 COR_BLOB_DATA_ITERIM           COR_BLOB_DATA_ITERIM           PREBUILT


   -----------------------------------------------------
4. Create constraints on the interim table
   -----------------------------------------------------

   Este punto no aplica.

   ------------------------------------------------------------
5. Simulamos actividad DML en la tabla origen
   -------------------------------------------------------------

   No Aplica

   --------------------------------------------------------------------------------
6. Se puede sincronizar la tabla con las nuevas transacciones
   --------------------------------------------------------------------------------

   BEGIN
   DBMS_REDEFINITION.SYNC_ITERIM_TABLE ('EXMRO, 'COR_BLOB_DATA', 'COR_BLOB_DATA_ITERIM');
   end;
   /

   PL/SQL procedure successfully completed.

   

   --------------------------------------------------------------
7. Previlegios necesarios para la tabla de paso.
   -----------------------------------------------------------------

   SQL> select * from USER_TAB_PRIVS_MADE;


   SQL> grant select, update on COR_BLOB_DATA_ITERIM to test;
   Grant succeeded.

   ---------------------------------------------------
8. Finalizamos porceso de re-organization
   ---------------------------------------------------



    PL/SQL procedure successfully completed.


   ----------------------------------
9. Limpiamos la tabla de paso
   ----------------------------------

    SQL> drop table COR_BLOB_DATA_ITERIM ;
    Table dropped.


    ----------------------------------
10. Renombramos las constraints
    ----------------------------------
Para las versiones RDBMS version 9.2, se puede renombrar las constraints:

Ejemplo:

    SQL> alter table emp rename constraint INT_EMP_PK to EMP_PK ;                        
    Table altered.



Nota
----

En ocasiones es necesario interrumpir el proceso de redefinition, para esto
se usa lo siguiente:


SQL>  execute dbms_redefinition.abort_redef_table('EXMRO','COR_BLOB_DATA','COR_BLOB_DATA_ITERIM');
PL/SQL procedure successfully completed.


11. Para monitorear el proceso de redefinition, consultamos lo siguiente:

[oracle@lstrmrobd01 lob]$ more longops.sql
set linesize 120
col opname format a20
col target format a15
col units format a10
col time_remaining format 99999990 heading Remaining[s]
col bps format 9990.99 heading [Units/s]
col fertig format 90.99 heading "complete[%]"
select sid,
       opname,
       target,
       sofar,
       totalwork,
       units,
       (totalwork-sofar)/time_remaining bps,
       time_remaining,
       sofar/totalwork*100 fertig
from   v$session_longops
where  time_remaining > 0
order by 9
/


SQL> @longops

       SID OPNAME               TARGET               SOFAR  TOTALWORK UNITS      [Units/s] Remaining[s] complete[%]
---------- -------------------- --------------- --------- ---------- ---------- --------- ------------ -----------
      3978 Table Scan           EXMRO.COR_BLOB_DATA  19423      21125 Blocks          0.20         8396       91.94
                                

12. Para optimizar el proceso de redefinition


Unos de los parametros del spfile, PARALLEL_THREADS_PER_CPU = 1
que esta seteado, para poder subir este parametro y ejecutar parallel query, se realizara una prueba
aparte , ademas se investiga este parametro y otros que pudiesen afectar el rendimiento de este proceso.

ALTER SESSION FORCE PARALLEL QUERY;
ALTER SESSION FORCE PARALLEL DML PARALLEL 8;
ALTER SESSION FORCE PARALLEL QUERY PARALLEL 8;


 

jueves, 11 de agosto de 2016

Segmentos LOBs Oracle

INTRODUCCION:

Las pruebas que se realizan en esta entrada son para mover campos LOBs, de una tabla especifica, esto se realiza con 2 metodos y 2 opciones por metodo.

1.- Metodo ALTER TABLE MOVE BLOB

1.1 Mover el campo aplicando securefile

1.2 Mover el campo aplicando basicfile

2.- Metodo DBMS_REDEFINITION

2.1 Mover el campo aplicando securefile

2.2 Mover el campo aplicando basicfile

LOBS se categorizan en CLOB (almacenan texto que contiene grandes cantidades de bytes),

-- NCLOB :(es similar al CLOB solo que almacena texto cuyo juego de caracteres está definido)

-- BLOB :(almacena información multimedia dentro de la base de datos)

-- BFILE :(similar al BLOB solo que la información multimedia está almacenada en el sistema          operativo).


Todo tipo de dato LOB tiene dos partes

a) LOB Value (es el contenido) el cual constituye el valor a almacenar por ejemplo: un texto o contenido multimedia.

b) LOB Locator, es un puntero a la ubicación del valor LOB (LOB Value) que es almacenado en la base de datos.

Si el texto o información multimedia se guarda dentro de la base de datos,
el contenido se almacena en un segmento separado de la tabla. Este segmento es de tipo LOB y almacena solo el LOB Value mientras
la tabla que se definió con él campo LOB solo lleva el LOB Locator como puntero al segmento LOB


Los valores LOB son almacenados out-of-line:

· Cuando se especifica explícitamente con la clausula DISABLE STORAGE IN ROW en la creación de la tabla.

· Cuando el tamaño del LOB es mayor que 3964 bytes (independientemente de las propiedades de la columna)

· Si se actualiza un LOB que está almacenado out-of-line y el LOB resultante es más pequeño de 3964 bytes,
  aún así sigue almacenado como out-of-line.

Los valores LOB son almacenados in-line cuando:

· cuando se crea la tabla no se especifica ningún parámetro en la clausula de almacenamiento del LOB.


· Se especifica explícitamente la clausula ENABLE STORAGE IN ROW cuando se crea la tabla, y el tamaño del LOB almacenado en la fila dada es pequeño,
  4K o menos.

· El valor del LOB es NULL (independientemente de las propiedades de almacenamiento de la columna)


Para este ejemplo moveremos segmentos LOBs de un tablespace a otro, de dos formas (ALTER TABLE MOVE y DBMS_REDEFINITION) y compararemos los beneficios y contra de cada estrategia.

1.- Creamos Una tabla

CREATE TABLE test_blob (
      id           NUMBER(15)
    , username     VARCHAR2(30)
    , file_name    VARCHAR2(1000)
    , image        BLOB
    , timestamp    DATE
)
/

Table created.

2.- Creamos un directoria para dejar un PDF.

CREATE OR REPLACE DIRECTORY DIR_TMP AS '/home/oracle/blob' /

Directory created.

 ktm.pdf

3.- Configuramos el archivo de control de Sqlloader:

oad_test_blob_data.ctl


load data
infile *
replace
into table test_blob

FIELDS TERMINATED BY ','
(
    id                   INTEGER external
  , username       CHAR
  , file_name       CHAR
  , image             LOBFILE(file_name)
                          TERMINATED BY EOF
                          NULLIF file_name='NONE'
  , timestamp            SYSDATE
)
begindata
1,JHUNTER,ktm.pdf

4.-Creamos un Procedimiento almacenado para introducir imagenes guardadas en un directorio y introducidas a un campo de tipo LOB, mediante
Sqlloader

write_blob_to_file.sql



CREATE OR REPLACE PROCEDURE "WRITE_BLOB_TO_FILE" AS

    -- +----------------------------------------------------+
    -- | PROGRAM VARIABLES                                  |
    -- +----------------------------------------------------+
    v_out_outdir          VARCHAR2(2000) := 'EXAMPLE_LOB_DIR';
    v_out_filename        VARCHAR2(500);
    v_out_filename_ext    VARCHAR2(4)    := '.out';
    v_out_filename_full   VARCHAR2(500);
    v_file_count          NUMBER         := 0;
    v_file_handle         UTL_FILE.FILE_TYPE;
 
    -- +----------------------------------------------------+
    -- | DYNAMIC SQL VARIABLES                              |
    -- +----------------------------------------------------+
    TYPE v_lob_cur_typ IS REF CURSOR;
    v_lob_cur             v_lob_cur_typ;
    v_sql_string          VARCHAR2(4000);
 
    -- +----------------------------------------------------+
    -- | BLOB WRITE VARIABLES                               |
    -- +----------------------------------------------------+
    v_blob_loc            BLOB;
    v_buffer              RAW(32767);
    v_buffer_size         CONSTANT BINARY_INTEGER := 32767;
    v_amount              BINARY_INTEGER;
    v_offset              NUMBER(38);
 
    -- +----------------------------------------------------+
    -- | EXCEPTIONS                                         |
    -- +----------------------------------------------------+
    invalid_directory_path EXCEPTION;
    PRAGMA EXCEPTION_INIT(invalid_directory_path, -29280);
 
    table_does_not_exist EXCEPTION;
    PRAGMA EXCEPTION_INIT(table_does_not_exist, -00942);
 
    invalid_identifier EXCEPTION;
    PRAGMA EXCEPTION_INIT(invalid_identifier, -00904);
 
    SQL_cmd_not_prop_ended EXCEPTION;
    PRAGMA EXCEPTION_INIT(SQL_cmd_not_prop_ended, -00933);
 
BEGIN

    -- +----------------------------------------------------+
    -- | ENABLE SERVER-SIDE OUTPUT                          |
    -- +----------------------------------------------------+
    DBMS_OUTPUT.ENABLE(1000000);
 
    v_sql_string := 'SELECT file_name, image FROM test.test_blob';
 
    OPEN v_lob_cur FOR v_sql_string;
 
    LOOP
 
        FETCH v_lob_cur INTO v_out_filename, v_blob_loc;
        EXIT WHEN v_lob_cur%NOTFOUND;
     
        v_file_count := v_file_count + 1;
        v_out_filename_full := v_out_filename || v_out_filename_ext;
     
        v_file_handle := UTL_FILE.FOPEN(v_out_outdir, v_out_filename_full, 'wb', 32767);
     
        v_amount := v_buffer_size;
        v_offset := 1;
     
        DECLARE
            invalid_LOB_locator EXCEPTION;
            PRAGMA EXCEPTION_INIT(invalid_LOB_locator, -06502);
     
        BEGIN
     
            WHILE v_amount >= v_buffer_size
            LOOP
                DBMS_LOB.READ(
                lob_loc    => v_blob_loc,
                amount     => v_amount,
                offset     => v_offset,
                buffer     => v_buffer);
             
                v_offset := v_offset + v_amount;
             
                UTL_FILE.PUT_RAW(
                file      => v_file_handle,
                buffer    => v_buffer,
                autoflush => true);
             
                UTL_FILE.FFLUSH(file => v_file_handle);
            END LOOP;
     
        EXCEPTION
     
            WHEN invalid_LOB_locator THEN
                UTL_FILE.PUT_LINE(file => v_file_handle, buffer => '+----------------------------+');
                UTL_FILE.PUT_LINE(file => v_file_handle, buffer => '|      ***   ERROR   ***     |');
                UTL_FILE.PUT_LINE(file => v_file_handle, buffer => '+----------------------------+');
                UTL_FILE.NEW_LINE(file => v_file_handle);
                UTL_FILE.PUT_LINE(file => v_file_handle, buffer => 'Invalid LOB Locator Exception for :');
                UTL_FILE.PUT_LINE(file => v_file_handle, buffer => '===================================');
                UTL_FILE.PUT_LINE(file => v_file_handle, buffer => '    --> ' || v_out_filename);
                UTL_FILE.NEW_LINE(file => v_file_handle);
                UTL_FILE.PUT_LINE(file => v_file_handle, buffer => 'SQL Text:');
                UTL_FILE.PUT_LINE(file => v_file_handle, buffer => '===================================');
                UTL_FILE.PUT_LINE(file => v_file_handle, buffer => '    --> ' || v_sql_string);
                UTL_FILE.FFLUSH(file => v_file_handle);
         
            WHEN others THEN
                UTL_FILE.PUT_LINE(file => v_file_handle, buffer => '+----------------------------+');
                UTL_FILE.PUT_LINE(file => v_file_handle, buffer => '|      ***   ERROR   ***     |');
                UTL_FILE.PUT_LINE(file => v_file_handle, buffer => '+----------------------------+');
                UTL_FILE.NEW_LINE(file => v_file_handle);
                UTL_FILE.PUT_LINE(file => v_file_handle, buffer => 'WHEN OTHERS ERROR');
                UTL_FILE.PUT_LINE(file => v_file_handle, buffer => '=================');
                UTL_FILE.PUT_LINE(file => v_file_handle, buffer => '    --> SQL CODE          : ' || SQLCODE);
                UTL_FILE.PUT_LINE(file => v_file_handle, buffer => '    --> SQL ERROR MESSAGE : ' || SQLERRM);
                UTL_FILE.FFLUSH(file => v_file_handle);
     
        END;
     
        UTL_FILE.FCLOSE(v_file_handle);

    END LOOP;
 
    CLOSE v_lob_cur;
 
    DBMS_OUTPUT.PUT_LINE('Wrote out ' || v_file_count || ' file(s) to ' || v_out_outdir || '.');

EXCEPTION

    WHEN invalid_directory_path THEN
        DBMS_OUTPUT.PUT_LINE('** ERROR ** : Invalid Directory Path: ' || v_out_outdir);
 
    WHEN table_does_not_exist THEN
        DBMS_OUTPUT.PUT_LINE('** ERROR ** : Table Not Found.');
        DBMS_OUTPUT.PUT_LINE('--> SQL: ' || v_sql_string);
 
    WHEN invalid_identifier THEN
        DBMS_OUTPUT.PUT_LINE('** ERROR ** : Invalid Identifier.');
        DBMS_OUTPUT.PUT_LINE('--> SQL: ' || v_sql_string);
 
    WHEN SQL_cmd_not_prop_ended THEN
        DBMS_OUTPUT.PUT_LINE('** ERROR ** : SQL command not properly ended.');
        DBMS_OUTPUT.PUT_LINE('--> SQL: ' || v_sql_string);

END;
/

SQL> @write_blob_to_file.sql

oracle@lpocrvmax01 [cisco1]$ sqlldr userid=test/test control=load_test_blob_data.ctl log=load_test_blob_data.log

Para sacar el tamaño del segmento LOB:

select segment_name, bytes, bytes/1024/1024 EspacioMB from user_segments where segment_name in ('TEST_BLOB');

Para obtener el scripts de la tabla:

SET LONG 10000
SELECT dbms_metadata.get_ddl('TABLE', 'TEST_BLOB',  'TEST') FROM dual;


Para obtener el tamaño y extensiones asociadas al tablespace:

column segment_name format a30
column tablespace_name format a13
set pagesiz 1000
select segment_name, sum(bytes) BYTES, TABLESPACE_NAME, count(*) EXTENTS
from user_extents
group by segment_name, TABLESPACE_NAME
order by 1;




SEGMENT_NAME                          BYTES     TABLESPACE   EXTENTS
------------------------------ ---------- ------------- ----------
SYS_IL0000091075C00004$$      4194304          TEST_AUTO 19
SYS_LOB0000091075C00004$$      4227858432 TEST_AUTO       246  
TEST_BLOB                                          65536     TEST_AUTO      1



SELECT SUM(bytes)/1024/1024 MB FROM dba_segments
 WHERE (owner = 'TEST' and segment_name = 'SYS_LOB0000091045C00004$$') 
    OR (owner, segment_name) IN (SELECT owner, segment_name FROM dba_lobs WHERE owner = 'TEST' AND table_name = 'TEST_BLOB');

4032 MB


Para obtener contenido del campo LOB:

select DBMS_LOB.SUBSTR(image, 5, 12) from TEST_BLOB;


Para mover el segmento (LOB Segment y Index Segment) debemos ejecutar el siguiente sql:


Aqui movemos los segmentos LOBs, a un nuevo tablespace aplicando la nuevas caracteristicas
de Oracle11g, SECUREFILE (Compression, deduplicacion y encriptacion)

SQL> ALTER TABLE TEST_BLOB MOVE LOB(IMAGE) STORE AS SECUREFILE (TABLESPACE TEST_AUTO_TMP COMPRESS HIGH DEDUPLICATE);

Table altered.


Elapsed: 00:10:17.72


RESULTADO:

SEGMENT_NAME    BYTES TABLESPACE_NA    EXTENTS
------------------------------ ---------- ------------- ----------
SYS_IL0000091075C00004$$    65536 TEST_AUTO_TMP 1
SYS_LOB0000091075C00004$$ 87162880 TEST_AUTO_TMP 14  <<==== (84 EspacioMB)
TEST_BLOB            65536 TEST_AUTO     1


SELECT SUM(bytes) BYTES FROM dba_segments
 WHERE (owner = 'TEST' and segment_name = 'SYS_LOB0000091045C00004$$') 
    OR (owner, segment_name) IN (SELECT owner, segment_name FROM dba_lobs WHERE owner = 'TEST' AND table_name = 'TEST_BLOB');

 83 MB



#######################################################################
Aqui movemos los segmentos LOBs, a un nuevo tablespace , dejando la propiedad basica, BASICFILE.

ALTER TABLE TEST_BLOB MOVE LOB(IMAGE) STORE AS BASICFILE
(TABLESPACE TEST_AUTO);

Nota Metalink: SecureFiles Migration and Accessing securefile metadata information  
[ID 1170351.1]

#######################################################################


ALTER TABLESPACE  TEST_AUTO_TMP ADD DATAFILE '+UCSRAC_DATA/cisco/datafile/test_auto_tmp2' size 4096m;

#######################################################################
AHORA REALIZAMOS LAS PRUEBAS CON DBMS_REDEFINITION
#######################################################################

1.- Sacamos el scrip de la creacion de la tabla:

select dbms_metadata.get_ddl('TABLE', 'TEST_BLOB', 'TEST')


CREATE TABLE "TEST"."TEST_BLOB_ITERIM"
   ( "ID" NUMBER(15,0),
"USERNAME" VARCHAR2(30),
"FILE_NAME" VARCHAR2(1000),
"IMAGE" BLOB,
"TIMESTAMP" DATE
   ) SEGMENT CREATION IMMEDIATE
  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255
 NOCOMPRESS NOLOGGING
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "TEST_AUTO"
 LOB ("IMAGE") STORE AS SECUREFILE (COMPRESS HIGH DEDUPLICATE
  TABLESPACE "TEST_AUTO_TMP" ENABLE STORAGE IN ROW CHUNK 8192 RETENTION
  NOCACHE NOLOGGING
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT));

Uso de Redefinition:


How to Re-Organize a Table Online (Doc ID 177407.1)


select bytes/1024/1024 "mb" from dba_segments where segment_name like 'TEST_BLOB' and owner='TEST'


select a.owner, a.table_name, a.column_name, a.segment_name , b.bytes/1024/1024 MB
from dba_lobs a, dba_segments b
where a.segment_name = b.segment_name
and a.owner = b.owner
and a.owner= 'TEST'
and a.table_name='TEST_BLOB'
order by b.bytes/1024/1024;

4032 MB


##############################################################################

GRANT que debe tener el usuario de redefinir:


GRANT CREATE ANY TABLE TO TEST;
GRANT ALTER ANY TABLE TO TEST;
GRANT DROP ANY TABLE TO TEST;
GRANT LOCK ANY TABLE TO TEST;
GRANT SELECT ANY TABLE TO TEST;
GRANT CREATE ANY INDEX TO TEST;
GRANT CREATE ANY TRIGGER TO TEST;

Ver si la tabla puede ser redefinida:

begin
dbms_redefinition.can_redef_table
 (uname=>'TEST',
 tname=>'TEST_BLOB',
 options_flag=>DBMS_REDEFINITION.CONS_USE_ROWID);
end;
/


ALTER SESSION FORCE PARALLEL DML PARALLEL 8;
ALTER SESSION FORCE PARALLEL QUERY PARALLEL 8;


1.- START Redefinition


SQL> set timing on

BEGIN
DBMS_REDEFINITION.START_REDEF_TABLE
 (uname=>'TEST',
 orig_table=>'TEST_BLOB',
 int_table=>'TEST_BLOB_ITERIM',
 options_flag=>DBMS_REDEFINITION.CONS_USE_ROWID);
end;
/SQL> 

PL/SQL procedure successfully completed.

Elapsed: 00:10:24.10



2.- Obtener errores del proceso de redefinition:

set timing off
vari num_errors number

BEGIN
DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS
 (uname=>'TEST',
 orig_table=>'TEST_BLOB',
 int_table=>'TEST_BLOB_ITERIM',
 num_errors=>:num_errors);
END;
/

PL/SQL procedure successfully completed.

SQL> print num_errors
NUM_ERRORS
----------

0


3.- finish_redef_table

begin
dbms_redefinition.finish_redef_table
 (uname=>'TEST',
 orig_table=>'TEST_BLOB',
 int_table=>'TEST_BLOB_ITERIM');
end;
/  

4. Drop table TEST_BLOB_ITERIM


5. Reduccion del tamaño de los segmentos LOBs

SELECT SUM(bytes)/1024/1024 MB FROM dba_segments
WHERE (owner = 'TEST' and segment_name = 'SYS_LOB0000091045C00004$$') 
OR (owner, segment_name) IN (SELECT owner, segment_name FROM dba_lobs
WHERE owner = 'TEST' AND table_name = 'TEST_BLOB');

97 MB


SEGMENT_NAME    BYTES TABLESPACE_NA    EXTENTS
------------------------------ ---------- ------------- ----------
SYS_IL0000091084C00004$$    65536          TEST_AUTO 1
SYS_LOB0000091084C00004$$ 101842944 TEST_AUTO 70
TEST_BLOB                                      65536  TEST_AUTO 1


#################################################################################
Procedimiento sin Advance Compress DBMS_REDEFINITION
#################################################################################


CREATE TABLE "TEST"."TEST_BLOB_ITERIM"
   ( "ID" NUMBER(15,0),
"USERNAME" VARCHAR2(30),
"FILE_NAME" VARCHAR2(1000),
"IMAGE" BLOB,
"TIMESTAMP" DATE
   ) SEGMENT CREATION IMMEDIATE
  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255
 NOCOMPRESS NOLOGGING
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "TEST_AUTO"
 LOB ("IMAGE") STORE AS BASICFILE (
  TABLESPACE "TEST_AUTO_TMP" ENABLE STORAGE IN ROW CHUNK 8192 RETENTION
  NOCACHE NOLOGGING
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT));


SQL> set timing on

BEGIN
DBMS_REDEFINITION.START_REDEF_TABLE
 (uname=>'TEST',
 orig_table=>'TEST_BLOB',
 int_table=>'TEST_BLOB_ITERIM',
 options_flag=>DBMS_REDEFINITION.CONS_USE_ROWID);
end;SQL>

PL/SQL procedure successfully completed.

Elapsed: 00:04:34.45


begin
dbms_redefinition.finish_redef_table
 (uname=>'TEST',
 orig_table=>'TEST_BLOB',
 int_table=>'TEST_BLOB_ITERIM');
end;
/

drop table TEST_BLOB_ITERIM


SEGMENT_NAME    BYTES                 TABLESPACE_NA           EXTENTS
------------------------------ ---------- ------------- ----------
SYS_IL0000091232C00004$$      4194304         TEST_AUTO_TMP 19
SYS_LOB0000091232C00004$$      4228907008 TEST_AUTO_TMP    247
TEST_BLOB                                              65536 TEST_AUTO             1

###############################################################################


SELECT SUM(bytes)/1024/1024 MB FROM dba_segments
 WHERE (owner = 'TEST' and segment_name = 'SYS_LOB0000091045C00004$$')
    OR (owner, segment_name) IN (SELECT owner, segment_name FROM dba_lobs WHERE owner = 'TEST' AND table_name = 'TEST_BLOB');

  4033 MB


#############################################################################
ALTER TABLE MOVE BLOB BASICFILE
#############################################################################

set timing on
ALTER TABLE TEST_BLOB MOVE LOB(IMAGE) STORE AS BASICFILE (TABLESPACE TEST_AUTO_TMP);


CONCLUSION

Las pruebas realizadas sobre el campo LOB, de la tabla TEST_BLOB campo LOB (IMAGE) al cual
cargamos un archivo PDF de 80 MB, 50 veces, generando 4022 MB de segmentos LOB (SYS_LOB0000091045C00004$$), 271 EXTENTS.

En ambos procedimientos de migracion del campo LOB, con alter tables move y dbms_redefinition (con y sin Advance Compress), los tiempos son similares tomando en cuenta el origen del LOB, mismos storage, Luns, velocidad de los discos, etc.


Las ventajas:

Con ALTER no genera redolog
Procedimiento mas simple

Con Redefinition la tabla que Online
se puede cambiar la estructura de la tabla y aplicando nuevas caracterisiticas.


Desventajas:

Con ALTER se deja indisponible la tabla por el tiempo que lleve mover los segmentos LOBs.


Con Redefinition genera redolog
Procedimiento mas complejo.
Se necesita espacio para tabla de paso.


Resultados en tiempo y Espacio:

1) Alter table move LOB SECUREFILE

Elapsed: 00:10:17.72 Con indisponibilidad de la tabla durante este lapso de tiempo.

Space: conserva el mismo tamaño de los segmentos.


2) dbms_redefinition Con SECUREFILE HIGH y DEDUPLICATE


Elapsed: 00:10:24.10 Con downtime 0

Space: Reduccion de EXTENTS de 256 a 70 , con Espacio en MB 100


3) dbms_redefinition Con BASICFILE

Elapsed: 00:04:34.45 Con downtime 0

Space: conserva el mismo tamaño de los segmentos.

4) Alter table move LOB BASICFILE

Elapsed: 00:04:28.92 Con indisponibilidad de la tabla durante este lapso de tiempo.

Space: conserva el mismo tamaño de los segmentos.