Sie sind auf Seite 1von 115

Curso

Dba para Desarrolladores

Impartido por: Luis Figueroa

Santa Cruz de la Sierra, Bolivia

Setiembre 1999
Índice
ÍNDICE .............................................................................................................................................................. 2

ORACLE, ARQUITECTURA INTERNA Y EXTERNA ..............................................................................4


CONCEPTOS GENERALES .................................................................................................................................4
BASES DE DATOS .............................................................................................................................................5
TABLESPACES ..................................................................................................................................................6
ARCHIVOS O DATA FILES .................................................................................................................................6
INSTANCIAS ..................................................................................................................................................... 7
ESTRUCTURAS INTERNAS DE LA BASE DE DATOS ............................................................................................ 7
ORACLE, ARQUITECTURA INTERNA Y EXTERNA ............................................................................ 14
SECUENCIAS .................................................................................................................................................. 14
PROCEDIMIENTOS .......................................................................................................................................... 14
FUNCIONES .................................................................................................................................................... 14
PAQUETES ALMACENADOS ............................................................................................................................ 15
TRIGGERS ...................................................................................................................................................... 15
DATABASE LINKS ........................................................................................................................................... 16
SINÓNIMOS .................................................................................................................................................... 16
PRIVILEGIOS Y ROLES .................................................................................................................................... 17
SEGMENTS, EXTENTS Y BLOCKS ..................................................................................................................... 18
ROLLBACK SEGMENTS ................................................................................................................................... 19
ORACLE, ARQUITECTURA INTERNA Y EXTERNA ............................................................................ 20
ESTRUCTURAS INTERNAS DE MEMORIA ......................................................................................................... 20
ESTRUCTURAS EXTERNAS ............................................................................................................................. 26
CONSIDERACIONES DE HARDWARE Y CONFIGURACIÓN............................................................. 28
VISIÓN GENERAL DE LA ARQUITECTURA ....................................................................................................... 28
SERVIDORES INDEPENDIENTES (STAND-ALONE HOSTS) ................................................................................ 29
SERVIDORES INDPENDIENTES CON ARREGLOS DE DISCOS ............................................................................ 30
SERVIDOR INDEPENDIENTE CON ESPEJEO DE DISCOS VIA SISTEMA OPERATIVO .............................................. 32
SERVIDORES INDEPENDIENTES CON MÚLTIPLES BASES DE DATOS .................................................................. 32
SERVIDORES ENLAZADOS EN RED .................................................................................................................. 33
PLANEAMIENTO LÓGICO DE LA BASE DE DATOS ........................................................................... 36
OPTIMAL FLEXIBLE ARQUITECTURE (OFA) .................................................................................................. 36
PLANEAMIENTO FÍSICO DE LA BASE DE DATOS .............................................................................. 40
DISTRIBUCIÓN DE LOS ARCHIVOS DE LA BASE DE DATOS ............................................................................... 40
CONTENCIÓN DE I/O ENTRE LOS DATAFILES .................................................................................................. 40
CUELLOS DE BOTELLA DE I/O ENTRE TODOS LOS ARCHIVOS DE LA BASE DE DATOS....................................... 41
I/O CONCURRENTE ENTRE LOS PROCESOS DE BACKGROUND .......................................................................... 42
UTILIZACIÓN DEL ESPACIO DENTRO DE LA BASE DE DATOS............................................................................ 46
OPERACIONES RUTINARIAS DE MANEJO FÍSICO DE ARCHIVOS DE ORACLE ..................................................... 53
LABORATORIO, INSTANCIAS Y TABLESPACES................................................................................. 55

LABORATORIO, ERRORES, CAMBIAR TAMAÑO DE DATAFILES, MOVER DATAFILES,


SCRIPT GENÉRICOS. .................................................................................................................................. 61
PROVOCAR UN ERROR IRRECUPERABLE.... ..................................................................................................... 61
MOVER DATAFILES, CAMBIO DE TAMAÑO Y AGREGAR DATAFILES................................................................. 61
VARIOS SCRIPTS ............................................................................................................................................. 62
AFINAMIENTO DEL SQL............................................................................................................................ 64
AFINANDO SINTAXIS ...................................................................................................................................... 65
EXPLAIN PLAN .......................................................................................................................................... 72
OPTIMIZADORES DE ORACLE ......................................................................................................................... 73
AFINAMIENTO DE LA UTILIZACIÓN DE MEMORIA......................................................................... 77
¿CÓMO DETERMINAR CUANDO RECONSTRUIR ÍNDICES? ................................................................................. 82
UTILIZACIÓN DE UTLBSTAT Y UTLESTAT ............................................................................................... 83
SQL TRACE FACILITY .................................................................................................................................... 83
LABORATORIO, TUNING SQL .................................................................................................................. 87

LABORATORIO, TKPROF Y OTROS SCRIPTS...................................................................................... 90

SEGURIDAD Y AUDITORÍA ....................................................................................................................... 92


CAPACIDADES DE SEGURIDAD ....................................................................................................................... 92
IMPLEMENTANDO LA SEGURIDAD .................................................................................................................. 93
AUDITANDO ................................................................................................................................................. 100
RESPALDO Y RECUPERACIÓN .............................................................................................................. 102
RESPALDOS LÓGICOS ................................................................................................................................... 102
RESPALDOS FÍSICOS ..................................................................................................................................... 103
IMPLEMENTACIÓN........................................................................................................................................ 104
OFFLINE BACKUPS ....................................................................................................................................... 107
BLOQUEOS .................................................................................................................................................. 110
DEADLOCKS ................................................................................................................................................ 111
LABORATORIO, AUDITORIA, RESPALDO Y RECUPERACION ..................................................... 114
AUDITORÍA Y SEGURIDAD ............................................................................................................................ 114
RESPALDO Y RECUPERACIÓN ....................................................................................................................... 115
BIBLIOGRAFÍA ........................................................................................................................................... 116
Oracle, arquitectura interna y externa

Conceptos Generales

Oracle es una base de datos relacional, con una gran diversidad de herramientas para
desarrollo de aplicaciones, administración de la base de datos y herramientas de
conectividad en redes (incluyendo el WEB).

Una de las grandes confusiones que tiene cualquier persona que comienza a trabajar con
Oracle es el confundir los diferentes productos que mercadea Oracle Corporation, mucha
gente tiende a confundir o denominar Oracle a todos los productos y esto lleva a
confusiones con los usuarios y entre las mismas personas de sistemas. Para aclarar este
tema a continuación detallo a continuación algunos de los productos de Oracle y su
clasificación para que quede claro dónde se ubica exactamente el producto “Oracle
Database Server” con respecto a toda la gama ofrecida por Oracle.

Productos de Base de Datos Oracle Database Server


Oracle Security Server
Oracle Parallel Server
...
Productos de Desarrollo de Aplicaciones Developer/2000
Designer/2000
Browser
...
Productos de Conectividad en Redes SQL*Net 2.3
Net8
Oracle Web Server

El modelo relacional empleado por Oracle, está bastante probado y su definición teórica
tiene más de 20 años de haber sido propuesta. Sin embargo no fue sino hasta bien
entrados los años 80 que fue posible dar soporte real a toda la teoría relacional, gracias al
abaratamiento de los discos duros y la memoria, ya que el modelo relacional requiere
mayores cantidades de estos recursos que los modelos anteriores de bases de datos
como el jerárquico y de redes.
Para aclarar términos que emplearemos en el resto del curso veamos el siguiente
esquema:

Por ejemplo veamos una tabla típica de departamentos en una empresa:


Nombres de las columnas

Num_depto Nombre Localización


Filas 1 o Ventas Santa Cruz
Rows 2 de Producción Cochabamba
datos 3 Administración La Paz
4 Cómputo Santa Cruz

Columnas de datos

Para accesar a estos datos, se utiliza un lenguaje de consultas denominado SQL, el cual
es un estándar utilizado por la mayoría de manejadores de bases de datos a nivel
mundial, sin embargo, Oracle a este SQL básico le ha agregado una gran variedad de
funcionalidad adicional lo cual lo hace el manejador de base de datos más popular hoy
día. El manejador de la base de datos utiliza estadísticas, índices y ayudas provistas por
el programador para extraer la información solicitada por un usuario, a este proceso se le
denomina “Optimizador” y será visto durante el transcurso del curso. Lo importante a
tener en cuenta es que siempre que se hace una consulta hay un proceso intermedio que
se encarga de determinar donde, cómo y qué datos traer de la base de datos.

Bases de Datos

Una base de datos es un conjunto de datos. Oracle provee la habilidad de almacenar y


accesar los datos de una manera consistente con el modelo relacional. Debido a que
Oracle es referido como una base de datos relacional, cuando digamos “base de datos”
nos referiremos no sólo a los datos físicos sino también a la combinación de datos,
memoria y procesos que explicaremos a continuación.

Los datos en una base de datos están almacenados en tablas, las tablas relacionales
están definidas por sus columnas las cuales tienen un nombre. Los datos se almacenan
en filas dentro de la tabla. Las tablas pueden relacionarse unas con otras y la base de
datos puede ser usada para obligar a cumplir con estas relaciones.

Internamente, Oracle almacena los datos en archivos, existen estructuras de la base de


datos que proveen un mapeo lógico entre los datos y estos archivos, permitiendo que
diferentes tipos de datos puedan ser almacenados en forma separada. Estas divisiones
lógicas se llaman tablespaces.
Tablespaces

Un tablespace es una división lógica de la base de datos, cada base de datos tiene al
menos un tablespace llamado SYSTEM, otros tablespaces pueden ser usados para
agrupar usuarios o aplicaciones por facilidad de administración asi como por beneficios de
rendimiento que explicaremos luego. Un tablespace SOLO puede pertenecer a una base
de datos.

Archivos o Data Files

Cada tablespace está compuesto de uno o más archivos llamados datafiles en disco. Un
datafile sólo puede pertenecer a un tablespace.

Una vez que un datafile a sido agregado a un tablespace, no puede ser borrado del
tablespace y no puede ser asociado con otro tablespace.

Si se almacenan multiples objetos de base de datos en múltiples tablespaces, entonces


se pueden separar físicamente a nivel físico colocando sus respectivos datafiles en discos
separados. Esta separación de datos es una herramienta importante de planeamiento y
afinamiento de la forma en que la base de datos utiliza el I/O del servidor.

Para ilustrar estas relaciones veamos el siguiente esquema:

Base de Datos

SYSTEM Segundo Tercer


Tablespaces Tablespace Tablespace Tablespace

Datafiles
Instancias

Para accesar los datos en la base de datos, Oracle utiliza un conjunto de procesos
concurrentes que son compartidos por todos los usuarios. Además existen estructuras de
memoria que son utilizadas para almacenar los datos de las consultas más recientes.
Estas áreas de memoria ayudan a mejorar el rendimiento de la base de datos
decrementando la cantidad de I/O realizado contra los datafiles.

Una instancia de base de datos es un conjunto de estructuras de memoria y procesos


concurrentes que accesa un conjunto de archivos de base de datos.

Los parámetros que determinana el tamaño y composición de una instancia son


almacenados en un archivo llamado init.ora. Este archivo es leído durante el arranque de
la base de datos y puede ser modificado or el DBA. Cualquier modificación hecha a este
archivo hasta la próxima vez que se arranque la base de datos. El archivo init.ora
normalmente se llama init+nombre de la instancia.ora, asi por ejemplo si la base de datos
se llama DESA, entonces el archivo de configuración se llamará initDESA.ora. Un
segundo archivo de configuracion, config.ora, es usado para almacenar caracteristicas
que NO cambian despues de creada la base de datos, tales como el tamaño del bloque.
Al igual que el init.ora, siguiendo el ejemplo el config.ora se llamará configDESA.ora.
Para que la configuracion del config.ora sea utilizada, en el init.ora debe haber un
parametro que se llama IFILE el cual debe tener el nombre y ruta del config.ora.

En resumen de un mismo servidor podría haber más de una instancia de Oracle, pero
sólo una copia del software de base de datos. Aunque lo más comun es que haya una
instancia por servidor y dependiendo del tamaño de la empresa varios servidores cada
uno con una instancia de Oracle, corriendo cada uno distintos conjuntos de datos, por
ejemplo un servidor con el sistema de Recursos Humanos y otro con el sistema de
Administración Financiera.

Estructuras internas de la Base de Datos

Dado lo que hemos visto hasta ahora, las estructuras de la base de datos Oracle pueden
dividirse en tres categorías:

Aquellas que son internas a la base de datos (como las tablas)


Aquellas que son internas a las áreas de memoria (como areas
compartidas de memoria y los procesos.
Aquellas externas a la base de datos (como los datafiles)

A continuación detallaremos el primer conjunto de estructuras, las internas.


Tablas, columnas y tipos de datos

Las tablas son el mecanismo para almacenar datos dentro de una base de datos Oracle.
Poseen un número fijo de columnas, las columnas de una tabla describen los atributos de
una entidad que está siendo mapeada a una tabla. Cada columna tiene un nombre y
características específicas.

Las características de una columna se componen de dos partes: el tipo de datos y la


longitu. Para columnas de tipo NUMBER, se puede especificar además la precisión y la
escala. La precisión determina el numero de dígitos significativos y la escala determina la
posición del punto decimal. Una especificación de NUMBER(8,2) para una columna
indica un total de ocho digitos, dos de los cuales están a la derecha del punto decimal. La
precisión por defecto es de 38 dígitos, la cuál también es la máxima precisión.

A continuación detallaremos los tipos de datos válidos en ORACLE (8.0.5):

Tipo de Datos Descripción


CHAR Un campo de longitud FIJA de hasta 2000 caracteres.
VARCHAR Actualmente es un sinónimo de varchar2, pero su funcionalidad
puede cambiar en futuras versiones de Oracle. No obstante se
recomienda utilizar varchar2 para literales de longitud variable.
VARCHAR2 Un campo de longitud variable de hasta 4000 caracteres
DATE Es un campo fijo de 7 bytes usado para almacenar fechas. El
tiempo también es almacenado como parte de la fecha.
NUMBER Una columna numérica de longitud variable. Los valores permitidos
son: cero y valores positivos y negativos de 1.0E-130 hasta
9.99E125
LONG Es un campo de longitud variable de hasta 2GB.
RAW Un campo de longitud variable utilizado para datos binarios de
hasta 4000 caracteres.
LONG RAW Es un campo de longitud variable para datos binarios de hasta
2GB.
MLSLABEL Se utiliza en una version especial de Oracle llamada “Trusted
Oracle”
BLOB Objetos binarios grandes de hasta 4GB de longitud.
CLOB Objetos carácter grandes de hasta 4GB de longitud.
NCLOB CLOB para conjuntos multicaracteres (japonés, chino, etc) de hasta
4GB.
BFILE Archivos binarios externos, su tamaño está limitado por el sistema
operativo donde corre Oracle.

Ademas de estos tipos de datos, en Oracle8 se pueden definir tipos de datos creados por
el usuario según se requiera, aunque siempre basados en los explicados anteriormente
que son los básicos.
Restricciones o Constraints

Una tabla puede tener constraints sobre ella, cuando un constraint es aplicado a una
tabla, cada fila de la tabla debe satisfacer las condiciones especificadas en la definición
del constraint. En el siguiente create table, se crea una tabla empleados con varios
constraints:

Create table employee


(empno number(10) primary key,
name varchar2(40) not null,
deptno number(2) default 10,
salary number(7,2) check salary < 1000000,
birth_date date,
soc_sec_num char(9) unique
foreign key(deptno) references dept.deptno)
tablespace users;

Primero, notemas que a la tabla se le da el nombre de EMPLOYEE, cada columna tiene


un nombre (empno, name, etc), cada columna tiene un tipo de datos y una longitud.

La llave primaria de la tabla es un constraint que se utiliza para identificar en forma única
cada fila, en el ejemplo definimos el empno como su llave primaria.

Por otro lado vemos el constraint NOT NULL aplicado al nombre, esto significa que la
base de datos validará que no sea posible meter un empleado con nombre nulo.

Otro constraint interesante es el unique, el cual hace que el campo soc_sec_num sea
unico dentro de la tabla, esto lo implemente la base de datos creando un índice único.

Por último tenemos el constraint foreign key, este se utiliza para que la base de datos
valide la integridad referencial automáticamente, esto es que el usuario no pueda crear un
empleado en un departamento inexistente!. En la vida real muchas veces se requiere por
ejemplo conocer todos los empleados de un departamento, es por esto que casi siempre
que un campo se utiliza para hacer referencia también se crea un índice por este campo
para mejorar el rendimiento de consultas típicas; en el caso de nuestro ejemplo
deberíamos crear un indice por deptno en la tabla EMPLOYEE.

Tipos de Datos Abstractos

A partir de Oracle8, se pueden definir tipos de datos propios. Por ejemplo se puede crear
un tipo de datos que contenga múltiples partes del nombre de una persona como un solo
tipo de datos:

Create type name_ty as object


(name varchar2(25),
primer_apellido varchar2(30),
segundo_apellido varchar2(30));
Se puede utilizar los tipos de datos definidos por el usuario para estandarizar el uso de
datos dentro de nuestras aplicaciones. Por ejemplo se puede utilizar el tyipo name_ty en
lugar de otros tipos de datos:

Create table employee


(empno number(10) primary key
name name_ty,
deptno number(2) default 10,
salary number(7,2) check salary < 1000000,
birth_date date,
soc_sec_num char(9) unique
foreign key(deptno) references dept.deptno)
tablespace users;

Particiones

A partir de Oracle8 se pueden especificar rangos que la base de datos utiliza para partir
una tabla muy grande en “tablas” más pequeñas. Estas tablas más pequeñas, llamadas
particiones, son más fáciles de manejar que tablas muy grandes. Por ejemplo, podemos
utilizar el truncate sobre una particion sin truncar los datos de otras particiones.

Las particiones tambien mejoran el rendimiento de una aplicación. Debido a que el


optimizador conoce los rangos de valores usados para crear la partición, es capaz de
dirijir las consultas para utilizar sólo ciertas particiones durante el acceso a las tablas.
Como se leen menos datos durante el procesamiento de la consulta, el rendimiento de la
consulta mejora.

También se pueden particionar índices igual que las tablas. Si los rangos de valores de
las particiones del indice son los mismos de la tabla particionada se llama un local index;
si las particiones del índice son diferentes a las de la tabla se llama un global index.
Un ejemplo de tabla particionada sería:

create table employee(


empno number(10) primary key,
name varchar2(40),
deptno number(2),
salary number(7,2),
birth_date date,
soc_sec_num varchar2(9),
constraint fk_deptno foreign key(deptno) references dept(deptno))
partition by range(deptno)
(
partition part1 values less than (11),
tablespace part1_ts,
partition part2 values less than (21),
tablespace part2_ts,
partition part3 values less than (31),
tablespace part3_ts,
partition part4 values less than (MAXVALUE),
tablespace part4_ts);

Usuarios

Una cuenta de usuario no es una estructura física en la base de datos, pero tiene una
gran importancia en sus relaciones con los objetos en la base de datos, los dueños de los
objetos son usuarios. Asi por ejemplo el usuario SYS posee el diccionario de datos,
donde se almacena información sobre el resto de estructuras de la base de datos.

Cuando se crean los objetos de una aplicación, se crean bajo una cuenta de usuario,
además a cada cuenta de usuario se le puede especificar el tablespace por defecto que
debe utilizar.

Esquemas

Un conjunto de objetos propiedad de una cuenta de usuario se llama esquema. Se


pueden crear cuentas de usuarios que no tengan la capacidad de conectarse a la base de
datos. Tales cuentas de usuario proveen un esquema para contener un conjunto de
objetos separado de los esquemas de usuarios. Por ejemplo si tenemos un Sistema de
Inventarios y creamos un usuario INV para almacenar sus objetos, INV sería un esquema,
el cual no debe ser accesado directamente por INV excepto en la creación; en producción
sólo debe ser accesado por usuarios con permisos para hacerlo.
Índices

En una base de datos relacional, la localización física de una fila es IRRELEVANTE, a


menos por supuesto que la base de datos necesite encontrarla. Para que sea posible
encontrar los datos, cada fila en la tabla tiene un pseudocolumna llamada RowID. Este
RowID le indica a la base de datos exactamente donde se encuentra la fila (por archivo,
bloque dentro del archivo y fila dentro del bloque).

Un índice es una estructura utilizada por el servidor para encontrar una fila rápidamente
dentro de una tabla. Existen tres tipos de índices: índices de cluster, índices de tablas y
índices bitmap.

Un índice contiene una lista de entradas, cada entrada consiste de un valor llave y un
RowId. El valor llave es el valor de una columna en una fila o la combinación de varias.
Las entradas en los índices de cluster y tablas son almacenados utilizando estructuras B*-
tree garantizando una ruta de acceso corta al valor llave. El I/O requerido para encontrar
una llave es mínimo y una vez encontrado el RowID es utilizado para accesar
directamente la fila.

Los índices se utilizan para mejorar el rendimiento y para asegurar la unicidad de una
columna. Oracle automáticamente crea un índice cuando se especifican las claúsulas
UNIQUE o PRIMARY KEY en un create table. Además se pueden crear índices
adicionales utilizando el comando create index.

A partir de la versión 7.3 de Oracle se pueden crear índices bitmap, los cuales son muy
útiles cuando los datos en alguna columna no son muy selectivos, o sea que la columna
tiene pocos valores distintos. Los índices bitmap incrementan la velocidad de búsqueda
cuando se requiere buscar datos por esas columnas. Los índices bitmap son más
efectivos cuando los datos almacenados en estas columnas son bastante estáticos, por
ejemplo el tipo de sexo.

Un ejemplo de cómo crear un índice bitmap sería:

create bitmap index IND_BITMAP_STAT_COD_EMPLOYEE


on EMPLOYEE(state_code);

Gráficamente un índice bitmap se puede expresar como:

FL: <1 1 1 1 1 0 0 0 0 0 >


CA: <0 0 0 0 0 1 1 1 1 1>

cada número representa una fila en la tabla EMPLOYEE. Debido a que hay 10 filas
consideradas hay 10 valores bitmap mostrados. El optimizador de Oracle puede
dinámicamente convertir las entradas de un índice bitmap a valores de RowID durante el
procesamiento de la consulta, esta capacidad de conversión le permite al optimizador
utilizar indices normales en conjunto con los bitmap.

Cuando se crean indices bitmap, Oracle comprime los bitmaps almacenados, como
resultado el espacio requerido para un índice de este tipo puede ser de sólo 5 o 10% del
espacio requerido por índice normal.
Vistas

Una vista se parece a una tabla porque tiene columnas y es consultada de la misma
forma que una tabla. Conceptualmente, una vista puede ser vista como una máscara que
se sobrepone a una o más tablas, tales que las columnas de la vista están basadas en un
o más tablas subyacentes. La definición de una vista (la cual incluye la consulta en la que
está basada, el formato de las columnas y los privilegios respectivos) está almacenada en
el diccionario de datos.

Cuando una vista es consultada, se consultan las tablas en las que está basada y retorna
los valores en el formato y orden especificados en la definición de la vista. Debido a que
no hay datos físicos asociados con ellas, las vistas NO pueden ser indexadas.

Las vistas son frecuentemente utilizadas para forzar la seguridad a nivel de filas sobre los
datos, por ejemplo se puede crear una vista para que cada empleado SOLO pueda ver los
datos de la tabla EMPLOYEE propios.

Por ejemplo, supongamos la siguiente tabla USUARIOS_X_DEPTNO y la tabla


EMPLOYEE:

create table usuarios_x_deptno(


empno number(10),
username varchar2(10));

ahora podríamos crear una vista V_EMPLOYEE:

create or replace view v_employee


as
select *
from employee e
where empno in (select empno
from usuarios_x_deptno
where username = USER);

Este esquema puede ser manipulado de acuerdo a las necesidas propias de cada
institución o empresa y aplicación.
Oracle, arquitectura interna y externa

Secuencias

Las secuencias son definiciones también almacenadas en el diccionario de datos. Las


secuencias son utilizadas para simplificar la programación proveyendo un lista secuencial
de números únicos.

La primera vez que una secuencia es utilizada en una consulta, retorna un valor
predeterminado; con cada subsecuente llamada es incrementada en un incremento
específico, normalmente 1. Las secuencias puede ser cíclicas o pueden seguir
incrementándose hasta que se alcanze un máximo especificado.

Un ejemplo de secuencia podría ser:

create sequence s_empleados


Start with 1 increment by 1;

Procedimientos

Un procedimiento es un bloque PL/SQL que es almacenada en el diccionario de datos y


es llamado por las aplicaciones según se requiera. Los procedimientos permiten
almacenar la lógica de las aplicaciones más utilizada dentro de la base de datos. Cuando
el procedimiento es ejecutado, sus sentencias son ejecutadas como una unidad. Los
procedimientos no retornan un valor al programa que los llamó.

Los procedimientos almacenados pueden servir para reforzar la seguridad de los datos.
Para lograr esto, no de grants directos de acceso a tablas a los usuarios dentro de una
aplicación. En lugar de esto, deles permiso de ejecutar procedimientos aque accesen las
tablas. Cuando el procedimiento es ejecutado, se ejecuta con los privilegios del dueño del
procedimiento. De esta manera los usuario serán incapaces de accesar las tablas
excepto vía el procedimiento.

Funciones

Las funciones así como los procedimientos son bloques de código que es almacenado en
la base de datos. Diferente a los procedimientos, las funciones retornan un valor al
programa que las llama. Incluso pueden ser utilizadas dentro de sentencias SQL al igual
que las funciones provistas por el SQL de Oracle.

Por ejemplo, Oracle provee una función llamada substr que extrae hileras de otras
hileras. Si creamos una funcion que se llama mi_substr que hace algo diferente,
podríamos utilizarla en un select de esta forma:
Select mi_substr(„text‟) from dual;

Sólo se puede utilizar una función dentro una sentencia SQL si la función no modifica
ninguna fila de la base de datos.

Paquetes Almacenados

Los paquetes son utilizados para conjuntar procedimientos y funciones en grupos lógicos.
Son muy útiles ya que facilitan la administración al conjuntar gran cantidad de
procedimientos y funciones.

Tienen un efecto secundario que debemos considerar, el cual es que como son
almacenados en el diccionario de datos, es probable que entre más lógica pongamos en
la Base de Datos, haya que agrandar el tablespace SYSTEM.

Por otra parte, los paquetes tienen la ventaja de ser compilados, por lo que su ejecución
es mucho más rápida, además por estar en la base de datos permanecen en memoria
mientras ésta no sea utilizada para otros efectos, con lo que un segundo y posteriores
usuarios que hagan uso de un paquete lograrán ejecuciones mucho más rápidas.

Triggers

Los triggers son procedimientos que son ejecutados cuando sucede un evento
especificado contra una tabla de la base datos. Se pueden utilizar para aumentar la
integridad referencial, reforzar la seguridad o mejorar las opciones de auditoría.

Existen dos tipos de triggers:

Statement triggers: Se disparan una vez por cada sentencia.

Row triggers Se disparan una vez por cada fila afectada en


la sentencia.

Para cada uno de estos tipos se puede crear un trigger AFTER y uno BEFORE para cada
evento disparador que son tres: INSERT, UPDATE y DELETE.
Database links

Las bases de datos Oracle tienen la capacidad de referenciar datos que se encuentran
fuera de la base de datos local. Cuando se referencian tales datos, se debe calificar el
objeto remoto en forma completa.

Las ligas de base de datos pueden ser públicas (disponibles para todas las cuentas de la
base) o privadas (solo para el usuario que la creó). Cuando se crea una liga de base de
datos se debe indicar el usuario y el password a la que se desea conectar así como el
nombre del servicio (SQL*Net tnsnames.ora) asociado a la base de datos remota. Si no
se indica el usuario y el password, Oracle intentará conectarse con el usuario y password
locales, los cuales de no existir en la base de datos remota producirá un error.

Por ejemplo:

Create public database link mi_liga


Connect to HR identified by ab1yu
Using „DBONE‟;

Sinónimos

Para identificar completamente un objeto de base de datos en una base de datos


distribuída, se debe especificar el servidor, la instancia, el dueño y el nombre del objeto.
Dependiendo de la localización del objeto entre uno y cuatro de estos parametros son
requeridos. Para aislar este proceso del usuario y proveer un acceso transparente al
usuario sin importar dónde se encuentren los datos se utilizan los sinónimos. Existen
sinonimos públicos (vistos por todos los usuarios) y sinónimos privados (vistos sólo por el
dueño del sinónimo).

Por ejemplo supongamos que la tabla EMPLOYEE está bajo el usuario HR, si no
existieran los sinónimos un usuario cualquiera tendria que digitar:

select * from HR.EMPLOYEE;

En cambio si creamos un sinónimo como:

create public synonym employee for hr.employee;

el usuario no tendría que importarle quien sea el dueño del objeto y digitaría:

select * from EMPLOYEE;

ahora bien, la utilidad de los sinónimos va más allá; cuando tenemos ambientes realmente
grandes en el que tenemos varios servidores, utilizamos los sinónimos para aislar al
usuario de esta complejidad utilizando sinónimos y ligas de base de datos:

create public synonym EMPLOYEE for hr.employee@mi_liga;


Privilegios y roles

Para accesar los objetos poseídos por otra cuenta de usuario, se debe haber dado
previamente el privilegio de accesar ese objeto.

Los permisos más comunes son insert, update, delete los cuales se otorgan sobre tablas
a un usuario o rol. También existe el privilegio execute para paquetes, funciones y
procedimientos almacenados.

Para utilizar los índices y triggers no se dan privilegios ya que son subyacentes a las
tablas mismas.

Ahora bien, en una empresa o institución existe la rotación de personal, algo inevitable
tanto como la vida y la muerte, por lo tanto si construimos un esquema de privilegios sólo
sobre usuarios, cuando alguno de éstos abandone la empresa o cambie de puesto, la
seguridad tendrá que recrearse o corremos el riesgo de dejar portillos abiertos al fraude.
Por esta razón existen los roles (puestos) estos nos ayudan a agrupar y definir nuestra
seguridad de acuerdo a un organigrama “oficial” de la empresa y luego asignamos o
revocamos estos roles a los usuarios según sea necesario.

Ahora veamos un caso, de un departamento típico de contabilidad:

create role r_contador_general;


create role r_auxiliar_contable;
create role r_secretaria_conta;

digamos que tenemos las tablas: cg_maestro_cuentas, cg_movimientos, cg_resumenes


podemos definir el siguiente esquema de seguridad:

grant select, insert, update, delete on cg_maestro_cuentas to r_contador_general;


grant select, update on cg_maestro_cuentas to r_auxiliar_contable;
grant select on cg_maestro_cuentas to r_secretaria_conta;
...

ahora supongamos que existen los usuarios: juan, pedro, javier, jose y maria:

grant r_contador_general to juan;


grant r_auxiliar_contable to pedro, javier, jose;
grant r_secretaria_conta to maria;

supongamos que jose renuncia y contratan a carlos para sustituirlo, la actualización será
muy simple:

revoke r_auxiliar_contable from jose;


grant r_auxiliar_contable to carlos;
Segments, extents y blocks

Los segmentos son la contraparte física de los objetos lógicos de la base de datos, los
segmentos almacenan datos. Los segmentos de índice, por ejemplo almacenan los datos
asociados con los índices. El manejo efectivo de los segmentos requiere que el DBA
conozca los objetos que utiliza una aplicación, cómo se ingresan los datos y las maneras
en que son accesados.

Debido a que un segmento es un entidad física, debe estar asignado a un tablespace en


la base de datos. Un segmento se construye de secciones llamadas extents, que son un
conjunto contiguo de bloques de Oracle. Cada vez que los extents de un segmento ya
dan cabida a nuevos datos, el segmento obtiene un nuevo extent. Este proceso de
extensión continúa hasta que no haya más espacio libre en el tablespace o hasta que un
máximo número de extents para el objeto sea alcanzado. Si un segmento tiene múltiples
extents, no hay garantía de que estos extents sean contiguos.

Ahora bien, Oracle utiliza para grabar y leer una medida llamada block, esta se debe
definir como mínimo igual al tamaño del bloque utilizado por el Sistema Operativo, 4096
bytes en la mayoría de equipos hoy día. Toda lectura o escritura se realiza en terminos
de bloques, o sea que siempre se lee o escribe como mínimo un bloque. Es por esto que
en bases de datos con mucha demanda de I/O se configura la base de datos con un
tamaño de bloque que sea múltiple del del sistema operativo por ejemplo 8K o 16K.

Detalle de la relación entre segmentos, extents y bloques.


Caracterísitcas de un bloque de datos:

Rollback segments

Para mantener la consistencia de lectura entre múltiples usuarios en la base de datos y


para tener la capacidad de “deshacer” transacciones, Oracle debe tener un mecanismo
para recontruir una imagen “antes de” de los datos que aún no se han grabado. Oracle
usa los rollback segments para cumplir con este propósito. Los segmentos de rollback
crecerán tanto como las transacciones que soportan.

Una transacción cualquiera en el sistema toma un segmento de rollback cuando empieza


y ese será el que utilize durante la vida de la transacción. En un ambiente de producción
debe haber en promedio un segmento de rollback por cada cinco usuarios de modo que
no haya mayores problemas con su manejo.
Oracle, arquitectura interna y externa

Estructuras Internas de Memoria

Existen dos tipos de estructuras de memoria diferentes utilizadas por Oracle: áreas
globales y procesos concurrentes (background process). Empezaremos estudiando las
estructuras de memoria globales utilizadas por todos los usuarios de la base de datos.

System Global Area (SGA)

Facilita la transferencia de información entre los usuarios. Además contiene la


información consultada mas comunmente acerca de la estructura de la base de datos.

Data Redo Dictionary Shared


Block Log Cache SQL
Buffers Buffers Pool

Data Block Buffer Cache

El data block buffer cache es un cache dentro del SGA usado para contener los bloques
de datos que son leídos desde la base de datos, tales como tablas, índices, y clusters. El
tamaño del data block buffer cache es determinado por el parámetro
DB_BLOCK_BUFFERS (del init.ora), expresado en términos de un número de bloques de
base de datos. Manejar el tamaño de este buffer es de gran importancia a la hora de
optimizar el rendimiento de la Base de Datos..

Debido a que el buffer cache es de tamaño fijo y más pequeño que el tamaño real
utilizado por los datos, no puede retener en memoria todos los datos en un momento
dado. Típicamente, el buffer cache es de un 1% o 2% del tamaño de la base de datos.
Oracle maneja el espacio disponible utilizando el algoritmo LRU, least recently used o el
menos utilizado recientemente. Cuando se necesita espacio libre en el cache, los bloques
menos usados recientemente serán escritos a disco y los nuevos bloques son leídos a
memoria. De esta memoria los datos más frecuentemente utilizados son mantenidos en
memoria.

Sin embargo, en una base de datos con muchas aplicaciones, es posible que haya
competencia entre ellas por el buffer cache, con lo cual puede suceder que bloques
utilizados frecuentemente salgan del cache a causa de la competencia, esto conlleva a
una baja frecuencia de éxitos en el cache, incrementado el I/O y degradando el
rendimiento de la Base de Datos.
Dictionary Cache

La información acerca de los objetos almacenados en la base de datos es almacenada en


las tablas del diccionario de datos. Esta información incluye las cuentas de usuario,
nombres de los datafiles, nombres de los segmentos, localizaciones de los extents,
descripciones de las tablas y priviliegios de acceso. Cuando esta información es
necesitada por la base de datos, por ejemplo para chequear los permisos de un usuario
para accesar un tabla, las tablas del diccionario son leídas y los datos son almacenados
en la SGA en el dictionary cache.

Este cache también es manejado con el algoritmo LRU explicado anteriormente. El


tamaño de este cache es manejado internamente por la base de datos, es parte del
shared SQL pool cuyo tamaño se define con el parámetro SHARED_POOL_SIZE del
archivo init.ora.

Redo Log Buffer

Los archivo redo log describen los cambios realizados en la base de datos. Los cambios
son escritos en estos archivos de modo que puedan ser utilizados en operaciones de
reconstrucción de la base de datos. Antes de ser escritos a los redo log files, las
transacciones son escritas primero en la SGA en un área llamada redo log buffer. La base
de datos entonces periódicamente escribe en lotes los datos del buffer en los archivo redo
log.

Shared SQL Pool

Almacena los datos del data dictionary cache y del library cache (información acerca de
instrucciones ejecutadas contra la base de datos). Esto es, mientras el data block buffer
y el dictionary cache, posibilitan el compartir información estructural y de información entre
los usuarios de la base de datos, el library cache permite compartir las sentencias SQL
más utilizados frecuentemente.

El shared SQL pool contiene el plan de ejecución y el parse tree para cada sentencia SQL
ejecutada contra la base de datos. La segunda vez que una sentencia SQL idéntica sea
ejecutada por cualquier usuario, es capaz de tomar ventaje de la información guardada en
el shared SQL pool para aligerar su ejecución.
Context Areas

Dentro del area compartida de SQL, existen áreas públicas y privadas. Cada sentencia
SQL emitida por un usuario requiere un área privada de SQL, la cual existe hasta que el
cursor asociado sea cerrado.

Program Global Area

Es un área en memoria utilizada por un proceso de usuario. Esta área NO es compartida.


Su función es almacenar los valores específicos de procesos de usuarios, datos e
información de control de cada proceso.
Background Process
Las relaciones entre las estructuras físicas y las estructuras de memoria es mantenida y
reforzada por los procesos concurrentes o de background. Estos varían en número
dependiendo de la configuración de la base de datos. Estos procesos son manejados por
la base de datos y requieren muy como trabajo administrativo. En la figura anterior se
muestra una configuración típica de Oracle con sus procesos concurrentes y estructuras
físicas y de memoria.

SMON

Cuando la base de datos arranca, el SMON (system monitor) realica la recuperación de


la base de datos si es necesario (utilizando los redo log files). También limpia la base de
datos, eliminando objetos transacciones que no sean necesitados por el sistema.

El SMON tiene un propósito adicional, “conjuntar” los extents libres que estén contiguos
para crear extents más grandes. La fragmentación del espacio libre será vista con más
profundidad más adelante, auqne los DBA deben realizar manualmente esta
compactación del espacio libre para algunos tablespaces ya que el SMON solo compacta
el espacio libre de los tablespaces que tengan un pctincrease distinto de cero.

PMON

El PMON limpia los procesos fallidos. Libera recursos que fueron utilizados por el
usuario, es responsalbe de liberar los bloqueos y hacerlos disponibles para otros
usuarios. Así como el SMON, el PMON se levanta periódicamente para chequear si se le
necesita.

DBWR

El DBWR (database writer) es responsable de manejar el contenido del buffer de datos o


data block buffer cache y el caché del diccionario. Lee los bloques de datos desde los
datafiles y los almacena en la SGA. También realiza escrituras en lotes de los bloques
cambiados. Optimizar las actividades del DBWR (eficiencia de lectura desde los datafiles
y eficiencia de lectura desde memria) constituye mucho de los efuerzos de optimización
realizados por los DBA.

Aunque existe sólo un SMON y un PMON por cada instancia de base de datos, es posible
tener múltiples procesos DBWR corriendo al mismo tiempo dependiendo de la plataforma
y sistema operativo. Utilizar múltiples DBWR ayuda a minimizar la contención dentro del
DBWR durante consultas muy grandes que involucran varios datafiles. El número de
DBWR es configurado con el parámetro DBWR_IO_SLAVES en el init.ora.
LGWR

El LGWR (log writer) maneja la escritura del contenido del redo log buffer hacia los redo
log files que estén en línea. Las entradas de este buffer siempre contienen el estado más
actualizado de la base de datos, debido a que el DBWR puede esperar antes de escribir
los bloques cambiados a los datafiles.

Los online redo log files, son escritos en forma secuencial. Si los redo log files están
“espejeados” el LGWR escribe simultaneamente a todas las copias.

ARCH

El LGWR escribe a los redo log files en línea en una manera cíclica, despues de llenar el
primer log file, empieza a escribir en el segundo hasta que se llene y entonces empieza a
escribir en el tercero. Una vez que el úlitmo redo log file es llenado, el LGWR
sobreescribe los contenidos del primer redo log file.

Cuando Oracle se corre en el modo ARCHIVELOG, la base de datos realiza una copia de
cada redo log file antes de sobrescribilo. Estos redo log files archivados se escriben casi
siempre a disco aunque tambien pueden ser escritos a cinta.

La función de archivo es realizada por el proceso ARCH. Las bases de datos podrían
encontrar problemas de contención durante transacciones muy pesadas, debido a que el
LGWR estará tratando de escribir a un redo log file mientras el ARCH está tratando de
leer otro. Pueden suceder bloqueos de la base si el disco donde se están archivando los
redo log files se llena. En este punto el ARCH se congela, lo cual previene que el LGWR
pueda escribir, lo cual impide cualquier otra transacción hasta que se libere espacio.

RECO

El proceso RECO es usado para resolver fallos en bases de datos distribuidas. El RECO
intenta accesar las bases de datos involucradas en transacciones que estén en duda y
resuelve las transacciones. Este proceso es sólo creado si la Opción Distribuida es
soportada en la plataforma y el parámetro DISTRIBUITED_TRANSACTIONS está
configurado a un valor mayor a cero en el init.ora.

SNPn

Las actualizaciones de snapshots y calendarizacion de la cola de trabajos interna confía


en un proceso de background para su ejecución. El nombre de este proceso empieza con
las letras SNP y termina con un número o letra. El número de procesos SNP creados
para una instancia es configurado con el parámetro JOB_QUEUE_PROCESS en el
init.ora en Oracle 8 y en Oracle 7 con el parámetro
SNAPSHOT_REFRESH_PROCESSES.
Estructuras Externas

Los datafiles descritos en las primeras lecciones, proveen el almacenamiento físico para
los datos de la base de datos. Aunque podemos decir que son internos y externo a la
vez, internos poque están relacionados directamente con la base de datos y externos
porque son archivos físicos.

Redo Logs

Oracle mantiene bitácoras de todas las transacciones realizadas contra la base de datos.
Estas transacciones son grabadas en archivos llamados online redo log files. Estas
bitácoras son usadas para recuperar las transacciones de la base de datos en el orden
apropiado en el evento de una caída.

Los redo log files, también le permite a Oracle optimizar la escritura a disco. Cuando
ocurre una transacción, es almacenada en el redo log buffer, mietrnas los bloques de
datos afectados no son escritos inmediatamente a disco. Esto le permite a la base de
datos realizar escrituras por lotes a los discos.

Cada base de datos Oracle tiene dos o mas online redo log files. Oracle escribe a los
online redo log files de manera cíclica, despues de llenar el primer log file, empieza a
escribir en el segundo hasta que se llene y entonces empieza a escribir en el tercero.
Cuando todos están llenos retorna al primer log file y empieza a sobreescribirlo. Si la
base de datos está corriendo en modo ARCHIVELOG, entones la base de datos realiza
copias de los online redo log files antes de sobreescribirlos. Estos log files archivados
pueden ser utilizados luego para recuperar la base de datos.

Los redo log files pueden ser “espejeados” parra una mayo seguridad en caso de falla
múltiple de discos.

Control Files

La arquitectura total de una base de datos es mantenida por sus control files, los cuales
almacenan información acerca de todos los archivos dentro de una base de datos. Son
utilizados paa mantener las estructuras internas consistentes y guiar las operaciones de
recuperación.

Debido a que los control files son CRÍTICOS para la base de datos, se almacenan
mútiples copias en línea. Estos archivos son almacenados típicamente en discos
SEPARADOS para minimizar el pontencial daño debido a fallas en los discos. La base de
datos creara y mantendrá la cantidad de control files especificado al momento de la
creación de la base de datos.
Trace Files y Alert Log

Cada uno de los procesos de background que estén corriendo en una instancia tiene un
archivo trace asociado con él. El trace file puede contener información acerca de eventos
significativos encontrados por los procesos. Además del trace file, Oracle mantiene un
archivo llamado alert log, que guarda los comandos y resultados de los eventos más
importantes en la vida de una base de datos, como por ejemplo: creación de tablespaces,
cambios de redo log, operaciones de recuperación y arranques o bajadas de la base de
datos. El alert log es una fuente de información vital paa el manejo diario de la base de
datos, los trace files se utilizan mayormente para descubrir la causa de una falla.
Consideraciones de Hardware y Configuración

Aunque cada base de datos Oracle puede ser construída con las mismas piezas básicas,
las opciones disponibles en cada caso depende de la plataforma de hardware y del
sistema operativo.

Visión General de la arquitectura

Una base de datos Oracle consiste de archivos físicos, áreas de memoria y procesos. La
distribución de estos componentes varía dependiendo de la arquitectura escojida.

Los datos en la base de datos son almacenados en archivos físicos en disco llamados
datafiles. Cuando son usados se almacenan en memoria. Oracle utiliza las áreas de
memoria para mejorar el rendimiento y para compartir datos entre usuarios. La memoria
principal en una base de datos es llamada System Global Área (SGA). Para leer y escribir
entre la SGA y los datafiles, Oracle utiliza un conjunto de procesos de background que
son compartidos por todos los usuarios.

Un servidor de base de datos, o instancia, es un conjunto de estructuras de memoria y


procesos de background que accesan un conjunto de datafiles, esta relación se ilustra a
continuación:

System Global Area

Server o
Instancia

Background Process

Database Database Files

Las caracterísitcas de la instancia, como el tamaño de la SGA y el número de procesos de


background, son especificados en el arranque a través de los parámetros del archivo
init.ora Este es leído unicamente durante el arranque, cualquier cambio posterior tendrá
efecto hasta el siguiente arranque.
Servidores Independientes (Stand-Alone Hosts)

Memoria

System Global Area

Server o
Instancia

Background Process

Unidad de Disco
Database
Database Files

La configuración conceptual más simple es un servidor que accesa una base de datos en
un servidor con sólo un disco. En esta configuración, todos los archivos son almacenados
en el único disco que posee, y sólo hay una SGA y un conjunto de procesos de
background.

Esta arquitectura representa la mínima configuración, todas las demás configuraciones


son modificaciones de estas estructuras básicas.

Los archivos almacenados en disco incluyen los datafiles y el archivo de configuración


init.ora. Existen dos puntos principales de interface en la base de datos:

Entre los datafiles y los procesos de background.


Entre los procesos de background y la SGA

Los esfuerzos de optimización constituyen mayoritariamente en mejorar estos puntos de


interface. Si el área de memoria dedicada a la base de datos es lo suficientemente
grande, entonces se realizarán menos lecturas repetitivas contra los datafiles. Debido a
que estos archivos están almacenados en un solo disco en esta configuración, se debería
tratar de minimizar la cantida de accesos a los datafiles.
Servidores Indpendientes con Arreglos de Discos

Memoria

System Global Area

Server o
Instancia

Background Process

Unidades de Disco
Database
Disco 1 Disco 2 Disco 3
Database Database Database
Files Files Files

Si se dispone de múltiples discos, entonces los datafiles pueden ser separados en discos
separados. Esto se hace para mejorar el rendimiento, reduciendo la cantidad de
contención de I/O entre los datafiles. Durante la operación de la base de datos, es común
que se requiera información de varios archivos para satisfacer una consulta. Si los
archivos no están distribuídos en varios discos, entonces el sistema necesitará leer
múltiples archivos en el mismo disco concurrentemente.

Espejeo de los Control Files

El archivo init.ora es almacenado en los directorios donde se haya instalado el software


de Oracle, normalmente en un directorio como
/orasw/app/oracle/admin/instance_name/pfile. El archivo init.ora no tiene los nombres de
los datafiles o de los online redo log, estos están almacenados dentro del diccionario de
datos. Sin embargo, el init.ora tiene los nombres de los control files para la base de
datos. En un servidor con múltiples discos, los control files debe almacenarse en discos
separados. La base de datos los mantendrá sincronizados. Almacenando los control files
en discos separados reduce el riesgo de problemas causados por fallos de disco.

Existe otro archivo de configuración llamado config.ora el cual es llamado por el init.ora.
El config.ora es usado para configurar los valores de aquellos parametros que NO
cambian dentro de la base de datos, los nombres de los control files están dentro de éstos
parámetros. Veamos un ejemplo del config.ora:
control_files =(/db01/oracle/ORA1/ctrl1ora1.ctl,
/db02/oracle/ORA1/ctrl2ora1.ctl,
/db03/oracle/ORA1/ctrl3ora1.ctl)

Si se desea agregar otro control file para mayor seguridad siga el siguiente procedimiento:

Baje la base de datos.


Copie uno de los control files actuales a una nueva localizacion en disco.
Edite el config.ora agregando el nuevo control file.
Arranque de nuevo la base de datos.

Espejeo de los Redo Log File

La base de datos puede automáticamente espejear los online redo log files. Para hacer
esto hay que utilizar los redo log groups.

Cuando se utiliza esta funcionalidad, el proceso LGWR escribe simultaneamente a todos


los miembros del online redo log group actual. O sean en vez de trabajar cíclicamente a
través de los online redo log files, lo hace pero cíclicamente a travez de los online redo
groups.

Los redo log groups pueden ser creados con el comando create database o alter
database. Por ejemplo:

alter database
add logfile group 4
(„/db01/oracle/CC1/log_1c.dbf‟,
„/db02/orace/CC1/log2c.dbf‟) size 5M;

Para agregar un nuevo redo log file a un grupo existente:

alter database
add logfile member „/db03/oracle/CC1/log_3c.dbf‟
to group 4;

Cuando se utiliza la opcion add logfile member, no se indica información de tamaño, esto
porque todos los miembros de un grupo deben tener el mismo tamaño.
Servidor Independiente con espejeo de discos via sistema operativo

Arreglo de discos 1 Arreglo de discos 2

Disco 1 Disco 1
Database Files Database Files

Disco 2 Disco 2
Database Files Database Files

Disco 3 Disco 3
Database Files Database Files

Muchos sistemas operativos posibilitan mantener copias duplicadas y sincronizadas de


archivos a través de lo que se llama disk shadowing conocido comunmente como
mirroring.

Existe dos beneficios al hacer este proceso. Primero, el conjunto adicional sirve como
respaldo en caso de una falla de disco. En la mayoría de los sistemas operativos, una
falla de disco causa que los discos correspondientes del espejo tomen el lugar de los
discos que han fallado. El segundo beneficio es la mejora en rendimiento, esto porque la
mayoría de los sistemas operativos que soportan esta arquitectura, pueden direccionar el
I/O para usar indistintamente cualquier disco, incluso los del espejo. Esto reduce la carga
por I/O en el conjunto de discos principal.

El tipo de espejo mostrado en la ilustracion se conoce como RAID-1. Dependiendo del


sistema operativo, existen otras opciones como RAID-3 o RAID-5.

Servidores independientes con múltiples bases de datos

Se pueden crear múltiples bases de datos en un mismo servidor. Cada base de datos
tendrá un conjunto separado de achivos y serán accesados por una instancia diferente.

Debido a que cada instancia requiere una SGA y procesos de background, el servidor
debe ser capaz de soportar los requerimientos de memoria y procesos suficientes.
Servidores enlazados en red

Cuando los servidores que tienen bases de datos Oracle son conectados a través de una
red, estas bases de datos entonces pueden comunicarse entre ellas a través de SQL*Net
o Net8.

Oracle kernel o aplicación

SQL*Net V2 / Net8

TNS

Driver específico al protocolo

Software del Protocolo

Como se muestra en la figura, los drivers de Net8 confían en el protocolo de red local para
lograr la conectividad entre dos servidores.

Las opciones de configuración en un ambiente en red son:

Redes de bases de datos, utilizados para consultas remotas.


Bases de datos distribuidas, utilizadas para transacciones remotas.
Bases de datos paralelas, en la cual múltiples instancias accesan la misma
base de datos.
Bases de datos cliente/servidor.

Redes de bases de datos

El Net8 permite transferir datos entre bases de datos. En su más simple configuración,
consiste de un proceso de servidor que espera conexiones via una ruta de conexión.
Cuando una de estas conexiones es detectada, sigue las instrucciones pasadas a través
de la conexión y luego retorna los datos solicitados.
Para que Net8 puede recibir y procesa las comunicacioness, el servidor debe estar
corriendo un proceso llamado el listener. El proceso listener debe estar corriendo en cda
servidor involucrado en la comunicación entre bases de datos.

Por ejemplo con Net8 o SQL*Net podemos realizar consultas remotas utilizando database
links, esta especifica el servidor, la base de datos y el usuario a utilizar en una consulta
remota. Veamos como se crea una database link:

create public database link MG_HR


connect to HR identified by HR
using „MG‟;

Ahora bien para realizar una consulta remota utilizando la liga de base de datos:

select * from empleados@MG_HR


where cod_depto = 10;

El concepto anterior puede ser expandido utilizando el Advanced Replication Option de


Oracle para realizar actualizaciones e inserciones en forma remota, haciendo uso como
en el ejemplo anterior de ligas de bases de datos.

En este caso, las transacciones distribuidas son controladas por Oracle a traves del Two-
Phase Commit o commit en dos fases. Si existiera un error en la red o falla un servidor,
puede suceder que los datos no estén sincronizados; para esto existe un proceso
background que resuelve estos problemas tan pronto como los recursos estén
nuevamente disponibles.

El número máximo de transacciones distribuidas para una base de datos se configura con
el parámetro DISTRIBUITED_TRANSACTIONES, si está en cero, no se permitirán
transacciones distribuidas y el proceso de recuperación en background no será
arrancado.

Cuando se dispone de multiples procesadores Oracle nos da las opciones Parallel Query
y Parallel Load, en la primera una consulta puede ser realizada por multiples
procesadores coordinadamente, esto mejora el rendimiento y tiempo de respuesta de las
transacciones.

La arquitectura Parallel Query de Oracle le permite a la base de datos paralelizar


operaciones. Las operaciones que pueden tomar ventaja de esta opción son: create table
as select, create index, recorridos completos de tablas, búsquedas en índices,
ordenamientos, inserciones, actualizaciones, borrados y la mayoria de las consultas.

Para configurar un servidor paralelo se parametrizan los valores de


PARALLEL_MAX_SERVERS y PARALLEL_MN_SERVERS en el init.ora
En el caso de que se desee utilizar la arquitectura cliente servidor, es necesario instalar el
Net8 o SQL*Net en cada PC para que puedan comunicarse:

Sistema Operativo Sistema Operativo


NIC
Software de Software de
Comunicaciones Comunicaciones

Oracle Software
SQL*Net o Net8
Oracle Database
Programas de Aplicación Ethernet
SQL*Net / Net8

En este caso la carga de CPU es distribuida entre el servidor y el cliente, aunque un


inconveniente muy fuerte de esta arquitectura es la gran utilización de red que realiza
transportando datos entre el sevidor y el cliente, problema que se agudiza aún más
cuando tenemos enlaces remotos de muy poco ancho de banda.
Planeamiento Lógico de la Base de Datos

Planear adecuadamante el diseño de la base de datos es de vital importancia para la vida


y rendimiento óptimo de cualquier base de datos Oracle.

Para distribuir los objetos, se debe establecer un sistema de clasificación. Los objetos
lógicos dentro de la base de datos deben ser clasificados basándose en cómo son usados
y en cómo sus estructuras físicas impactan la base de datos. Esto incluye separar tablas
de los índicies y tablas de gran actividad de las que tienen poca actividad. Aunque el
volumen de actividad contra objetos sólo puede determinarse durante la fase de
producción, un conjunto inicial de tablas muy utilizadas puede separarse inicialmente.

Optimal Flexible Arquitecture (OFA)

El tablespace SYSTEM

Es posible aunque no recomendable almacenar todos los objetos de la base de datos en


un solo tablespace, esto sería como guarda todos los archivos en el directorio raíz de un
disco. Este tablespace es donde se localizan las tablas del diccionario de datos y el
rollback de SYSTEM.

No hay razon para que haya algun otro objeto que no sea el diccionario o este segmento
de rollback. Almacenar otros objetos en el tablespace SYSTEM incrementa la posibilidad
de que haya problemas de espacio, lo cual requiere que el tablespace sea recreado.
Como la única posibilidad de reconstruir el tablespace SYSTEM es recrear la base de
datos, cualquier cosa que pueda ser movida fuera de SYSTEM debe ser movida.

Los segmentos del diccionario de datos almacenan toda la información acerca de los
objetos en la bas de datos. Son almacenados en el tablespace SYSTEM y son
generalmente estáticos a menos que haya cambios estructurales muy grandes dentro de
las aplicaciones. Lo que hace crecer el diccionario de datos en mayor medida son los
triggers y procedimientos almacenados de PL/SQL.

Para prevenir que los usuarios puedan crear objetos en el tablespace SYSTEM, podemos
definir una cuota de cero para todos los usuarios que creeemos:

alter user JDURAN quota 0 on SYSTEM;

Por otra parte cuando creamos un usuario podemos indicarle un tablespace por defecto,
tambien se puede hacer si ya existe:

create user JDURAN identified by chepe


default tablespace RH;
o
alter user JDURAN default tablespace RH;

Separar los segmentos de datos de aplicación: DATA


Los segmentos de datos son las áreas físicas en las cuales los datos asociados con las
tablas son almacenados. Estos segmentos tienden a ser accesados muy a menudo en un
ambiente en producción.

Un tablespace DATA típico contiene todas las tablas asociadas con una aplicación. Los
altos volúmenes de tráfico contra estas tablas la hacen un candidato ideal para ser
aisladas en un tablespace propio. Si se separan las tablas de aplicación en su propio
tablespace, significa que puede ser separado físicamente de otros datafiles en la base de
datos. Esta separación de datafiles a traves de las unidades de discos puede mejorar el
rendimiento (a través de una menor contención de I/O) y un manejo más sencillo de la
base de datos.

Los segmentos en un tablespace DATA, tienden a fragmentarse con el transcurso del


tiempo, con lo que como veremos más adelante, al estar separado, es mucho más fácil su
desfragmentación futura.

Separar los segmentos de índices de aplicación: INDEXES

Los índicies asociados con tables están sujetos al mismo I/O y fragmentación que los
datos. Los segmentos de índice NO deben ser almacenados en el mismo tablespace que
los datos asociados a ellos, debido a que tienen una gran cantidad de acceso concurrente
durante la manipulación y consulta de los datos.

Los segmentos de índice también están sujetos a fragmentación debido a una estimación
de tamaño errónea o un crecimiento impredecible. Aislar los índices de la aplicación en
un tablespace separado reduce grandemente los esfuerzos de administración
involucrados cuando se quiera desfragmentar ya sea el tablespace DATA o el INDEXES.

Separar índices existentes de sus respectivas tablas puede ser logrado mediante la
opción rebuild del comando alter index. Si un índice ha sido creado en el mismo
tablespace que su tabla, puede ser movido facilmente:

alter index i_empl_depto rebuild


tablespace INDEXES
storage (initial 2M next 2M pctincrease 0);
Separar segmentos de Herramientas: TOOLS

A pesar de lo que hemos visto de no almacenar segmentos de datos en el tablespace


SYSTEM, muchas herramientas hacen precisamente eso. No lo hacen exactamente
porque precisen que sus objetos estén en el tablespace SYSTEM, sino porque deben
utilizar el usuario SYSTEM para hacer la instalación y el usuario SYSTEM tiene el
tablespace SYSTEM por defecto. Para evitar esto cambie el usuario SYSTEM para que
su tablespace por defecto sea TOOLS y quitele las coutas a SYSTEM sobre el tablespace
SYSTEM:

alter user SYSTEM quota 0 on SYSTEM;


alter user SYSTEM quota 50M on TOOLS;

Separar los segmentos de Rollback: RBS

Los segmentos de rollback mantienen la consistencia de datos dentro de la base de


datos. Debido a que incurren en mucho I/O lo aconsejable siempre es aislarlos en un
tablespace dedicado a solo segmentos de rollback (RBS).

Una vez que el tablespace RBS ha sido creado, es conveniente desactivar el segmento
de rollback que existen en SYSTEM pero NO BORRARLO, ya que puede ser
imprescindible en caso de un problema con el tablespace RBS.

Los segmentos de rollback se expanden dinámicamente al tamaño de la transacción más


grande y se encojen hasta el tamaño óptimo especificado. El I/O contra los segmentos de
rollback es casi siempre concurrente con el I/O realizado contra DATA e INDEXES.
Separarlos nos ayuda a reducir la contención de I/O y facilita la administración.

Separar los segmentos temporales: TEMP

Los segmentos temporares son objetos creados dinámicamente dentro de la base de


datos para almacenar durante largas operaciones de ordenamiento tales como: select
distinct, union y create index. Debido a su naturaleza dinámica, los segmentos
temporales no deben ser almacenados junto con ningún otro tipo de segmento.

También es importante considerar al crear o modificar un usuario, especificar el segmento


para objetos temporales ya que por defecto el tablespace para objetos temporales es
SYSTEM:

create user JDURAN identified by chepe


default tablespace RH
temporary tablespace TEMP;
o
alter user JDURAN temporary tablespace TEMP;
Otros tablespaces

También puede ser necesario crear otros tablespaces como USERS, para que los
usuarios creen sus objetos, aunque esto no es muy común.

Además puede ser recomendable crear un tablespace DATA_2 e INDEXES_2, para


almacenar en estos datos e índices de poca utilización o muy estáticos como catálogos,
etc., esto aumenta el rendimiento de las aplicaciones y facilita la administración de la
base de datos.

A veces puede ser necesario tambien crear un tablespace de rollback, sobretodo cuando
se está en procesos de migración, durante los cuales se hacen importaciones masivas de
datos, que pueden resultar en que los segmentos de rollback definidos no sean
suficientes. Para esto podemos crear un tablespace RBS_2 y antes de empezar a hacer
la carga de datos ejecutamos:

set transaction use rollback segment segment_name;

Pueden existir dependiendo de la empresa o institución otros tablespaces que deben ser
separados como para contener los snapshots, particiones (Oracle8) o algún tablespace
temporal utilizado en cargas o migraciones.

Podemos decir que la configuración lógica de la base de datos es algo de sentido común
que podemos resumir como:

Tipos de segmentos que son usados en una misma manera deben


almacenarse juntos.
El sistema debe diseñarse para un uso estandarizado.
Áreas separadas deben existir por excepciones.
La contención entre tablespaces debe debe ser minimizado.
El diccionario de datos debe ser aislado.
Planeamiento Físico de la Base de Datos
Nunca dejes para mañana lo que puedes hacer hoy.

Muy a menudo, el planeamiento físico de una base de datos Oracle, sólo se toma en
cuanto cuando los problemas ya han surgido a la superficie en un sistema en producción,
cuando el costo de afinamiento es muy alto y peligroso.

Por otra parte nos enfrentamos a un problema de costo/beneficio, ya que siempre


tendremos más archivos de la base de datos que discos físicos a utilizar, por lo cual
debemos tomar varias decisiones en cuanto a como y cuales archivos distribuir en cada
disco.

En esta clase veremos varios aspectos físicos a considerar ANTES de crear cualquier
base de datos.

Distribución de los archivos de la base de datos

Contención de I/O entre los datafiles

Cuando diseñamos una base de datos tal y como vimos en la clase anterior, tendremos
una colección de tablespaces, cada una de las cuales necesitará por lo menos un datafile,
se puede monitorear el I/O entre datafiles después de que la base de datos ha sido
creada, pero a menos que tengamos a mano una base de datos con cargas o sistemas
similares, el DBA deberá estimar la carga de I/O para cada datafile.
Empiece estiamando el I/O relatvio de los datafiles. Asigne al tablespace más activo un
peso de 100, luego estime el I/O de los demás datafiles de manera relativa a este
tablespace. Asigne al tablespace SYSTEM un peso de 35 y a los tablespaces de índices
un tercio del peso del tablespace asociado.

Por otro lado con respecto al tablespace TOOLS, en ambientes de producción su


utilización es muy bajo, por lo que su peso relativo debe ser menor a 5. El tablespace
RBS depende del tipo de base de datos, si se realizan muchas transacciones puede llegar
a pesar hasta 75, aunque en la mayoría de los casos su peso va de 10 a 40. El TEMP,
en un ambiente en producción sólo se utiliza en operaciones de sort grandes, por lo que
su valor depende de cómo estén implementados nuestros sistemas y puede fluctuar entre
0 y 75.

Veamos un ejemplo:
Tablespace Peso % del Total
DATA 100 45
RBS 40 18
SYSTEM 35 16
INDEXES 33 15
TEMP 5 2
DATA_2 4 2
INDEXES_2 2 1
TOOLS 1 1
220
Notese que el 94% del I/O se concentra en los cuatro tablespaces iniciales, teóricamente
deberíamos tener cinco discos para una óptima implementación física de la base de
datos, dejando cuatro discos sólo para los primeros cuatro tablespaces, uno para cada
uno. Ahora bien como veremos más adelante y como sucede en la vida diaria, los
recursos son escasos la mayoría de las veces, por lo que este caso teórico no es muy
común y al final terminaremos teniendo menos discos de los que teóricamente
quisiéramos. Incluso, en teoría podriamos desear tener una controladora de disco para
cada disco, optimizando mucho más el modelo y evitando algún cuello de botello en la
tarjeta controladora.

Cuellos de botella de I/O entre todos los archivos de la base de datos


(otros que no sean datafiles)

Online Redo Log Files

Como hemos visto los redo log files almacenan cada transacción realizada en la base de
datos, cada base de datos debe tener al menos dos online redo log files.

Estos archivos son el talón de Aquiles de la base de datos. Como mantienen información
acerca de las transacciones actuales, no pueden ser recuperados de un respaldo anterior.
Es el único archivo que no puede ser recuperado a través de los utilitarios de respaldo.

Por esta razón el DBA debe asegurarse de tener los online redo log files, espejeados de
alguna manera. Dentro de Oracle, como vimos previamente los redo log groups nos
permiten lograr este objetivo.

En general, deberiamos tratar de tener los online redo log files aparte de los datafiles
debido a problemas potenciales de rendimiento.

Cualquier transacción que no tengal el parámetro nologging es grabada en los redo log
files. Estas son escritas por el LGWR, los datos en la transacción son escritos a los
tablespaces vía DBWR. Esto significa que aunque el I/O puede ser distribuido
adecuadamente, puede ocurrir contención entre el DBWR y el LGWR si un datafile es
almacenado en el mismo disco que un redo log file.

Los redo log files son escritos SECUENCIALMENTE. Esto es si no hay actividad
concurrente en el disco, entonces el hardware del disco estará posicionado correctamente
para la siguiente escritura. En contraste, los datafiles son leídos y escritos en una forma
más o menos aleatoria. Debido a que los log files son escritos secuencialemente, serán
procesados en forma más rápida si no tienen que competir con otra actividad en el disco.

Si tenemos que guardar un datafile junto con uno o más redo log files, entonces no debe
se ni SYSTEM, RBS, DATA o INDEX. Todos estos tendrán problemas direcots con los
redo log files e incrementarán la posibilidad de que las escrituras de los log files sean
afectadas por lecturas de la base de datos.
Control Files

Con respecto a estos diremos que el I/O relacionado con ellos es prácticamente nulo y de
lo único que tenemos que preocuparnos como explicamos en la clase anterior es de tener
varias copias en distintos discos para prevenir su pérdida en caso de fallo de discos.

Archived Redo Log Files

Cuando Oracle se corren en modo ARCHIVELOG, la base de datos realiza una copia de
cada online redo log file antes de sobrescribirlo. Estos redo log files archivados son
normalmente escritos a un disco.

Esta función de archivo es realizada por el proceso ARCH como se explicó


anteriormente. Las bases de datos que utilizan esta opción podrán encontrar problemas
de contención en el disco donde se encuentren los online redo logs duarante
transacciones que modifiquen datos en forma masiva, debido a que el LGWR estará
tratando de escribir a un redo log mientras el ARCH está tratando de leer otro. La única
manera de evitar esta contención es distribuir los online redo log files a través de varios
discos.

También se debe ser muy cuidadose en cuando al disco donde se grabarán los archived
redo log files, ya que por su naturaleza demandan una cantidad de I/O similar a los online
redo log. Por lo tanto siga las mismas reglas expresadas para estos.

Oracle Software

El I/O contra el software de Oracle no queda registrada y por lo tanto no hay una manera
directa de conocer el impacto del I/O respectivo.

Lo más aconsejable es instalar el software de Oracle en un disco donde no haya datafiles,


aunque en caso de que sea necesario, debemos colocar en dicho disco los datafiles que
sean accesados en menor grado.

I/O concurrente entre los procesos de background

Cuando se evalúa la contención entre varios procesos es importante identificar el tipo de


I/O realizado y la oportunidad con que se realiza. Los archivos contienden entre si, si el
I/O de un archivo interfiere con el I/O de un segundo archivo, de modo que dos archivos
accesados en forma aleatoria que nunca son accesados al mismo tiempo pueden ser
ubicados en el mismo disco.

Basándonos en lo anterior, podemos definir dos tipos de contención de I/O: concurrente e


interferencia. La contención de I/O concurrente ocurre cuando se realizan múltiples
accesos contra el mismo disco al mismo momento. Esta es la clase de contención que
se elimina aíslando las tablas de sus respectivos índices. La contención por interferencia
ocurre cuando las escrituras secuenciales de un archivo son interrumpidas por lecturas o
escrituras de otros archivos en el mismo disco, aún si estas ocurren en momentos
distintos a las lecturas o escrituras secuenciales.

Existen tres procesos background de la base de datos que accesan activamente los
archivos en disco: el Database Writer (DBWR), el Log Writer (LGWR) y el Archiver
(ARCH) si se utiliza la opción ARCHIVELOG. El DBWR, escribe y lee los archivos en
forma aleatoria, el LGWR escribe secuencialmente y el ARCH lee y escribe
secuencialmente. Eliminando las posibilidades de contención entre estos tres procesos
efectivamente elimina la contención a nivel de la base de datos.

Notese que el LGWR y el ARCH, SIEMPRE escriben a un solo archivo a la vez, mientras
que el DBWR, escribe a varios archivos a la vez por lo que puede causar contención a si
mismo!. Para evitar esto en algunas plataformas como UNIX, se pueden definir varios
DBWR con el parámetro DBWR_IO_SLAVES, Oracle recomienda configurar este
parámetro igual al número de disco o hasta un máximo de dos por disco.

En todo caso, no importa que hagamos, la recuperabilidad de la base de datos siempre


debe ser el primer objetivo en cuenta. Una vez que estemos seguros de que podemos
recuperar bajo cualquier circunstancia la base de datos, debemos preocuparnos del
rendimiento, o sea no sacrifiquemos seguridad por desempeño nunca.

Configuración Física de la Base de Datos

Cuando nos sentemos a definir qué archivos irán en que discos tenemos muchas
alternativas o pocas dependiendo como hemos dicho de los recursos, si tuvieramos
recursos ilimitados y que podamos incluso subutilizar, entonces pongamos un disco para
tablespace, uno para archived redo logs, otro para hacer exports, etc.; pero esto no es
francamente muy económico por lo que siempre deberemos tomar decisiones en base al
peso relativo de cada archivo tomando como parámetro la tabla que construimos al
principio.

Veamos un caso hipotético de distribución teniendo como límite siete discos en un


servidor:

Disco Peso Contenido


1 Oracle Software
2 38 SYSTEM, TOOLS,
INDEXES_2 y Control File 1
3 40 RBS, RBS_2, Control File 2
4 100 DATA, Control File 3
5 42 INDEXES, TEMP, DATA_2
6 40+ Online Redo Logs 1, 2 y 3,
Export
7 40+ Software de aplicación,
archived redo logs
Verificación de las estimación de I/O

Ahora que hemos realizado esta configuración, la cual fue elaborada con base a nuestra
experiencia personal o de conocidos, el trabajo del DBA consiste en medir si en realidad
su estimación es cercana a la realidad, para esto usaremos el siguiente script:

REM This script will only work in 7.2 and above.


set pagesize 60 linesize 80 newpage 0 feedback off
ttitle skip center "Database File IO Weights" skip center -
"ordered by Drive" skip 2
column Total_IO format 999999999
column Weight format 999.99
column file_name format A40
break on Drive skip 2
compute sum of Weight on Drive

select
substr(DF.Name, 1,5) Drive,
DF.Name File_Name,
FS.Phyblkrd+FS.Phyblkwrt Total_IO,
100*(FS.Phyblkrd+FS.Phyblkwrt)/MaxIO Weight
from V$FILESTAT FS, V$DATAFILE DF,
(select MAX(Phyblkrd+Phyblkwrt) MaxIO
from V$FILESTAT)
where DF.File# = FS.File#
order by Weight desc

spool io_weights
/
spool off

Con los resultados que nos de este script podriamos valorar algún acomodo posterior a lo
que hemos planeado previamente.
A continuación listo un ejemplo de una corrida de este script en el servidor de producción
de la Mutual Guapay:

Database File IO Weights


ordered by Drive

DRIVE FILE_NAME TOTAL_IO WEIGHT


----- ---------------------------------------- ---------- -------
/i/b2 /i/b2000/dbs/data/ccd01.dbf 1647150 100.00
***** -------
sum 100.00

/d/b2 /d/b2000/dbs/instancia/temp/temp01.dbf 190448 11.56


***** -------
sum 11.56

/g/b2 /g/b2000/dbs/data/bcgd01.dbf 99726 6.05


***** -------
sum 6.05

/e/b2 /e/b2000/dbs/instancia/roll/roll01.dbf 23932 1.45


***** -------
sum 1.45

/h/b2 /h/b2000/dbs/ind/bcgi01.dbf 17127 1.04


***** -------
sum 1.04

/f/b2 /f/b2000/dbs/data/pad01.dbf 14860 .90


/f/b2000/dbs/ind/cci01.dbf 10558 .64
***** -------
sum 1.54

etc...
Utilización del espacio dentro de la base de datos

Cuando un tablespace es creado, los datafiles son creados para contener sus datos,
estos archivos resevan el espacio inmediatamente durante su creación a nivel de sistema
operativo.

En resumen una base de datos puede tener muchos tablespaces y cada tablespace
puede tener muchos datafiles. Una base de datos puede tener muchos usuarios llamados
esquemas. Cada esquema es una colección de objetos lógicos de base de datos tales
coo tablas e índices. Estos objetos se refieren a estructuras de datos físicas queson
almacenadas en tablespaces. Los objetos de un un usuario son pueden estar
almacenados en múltiples tablespaces, y un solo tablespace puede contener objetos de
múltiples esquemas.

Cuando se crea un objeto como tabla o índice, es asignado a un tablespace en particular


creando un segmento en este tablespace para contener los datos asociados a este objeto.
El espacio reservado para este segmento NUNCA es liberado hasta que el segmento sea
eliminado, reducido o truncado (drop, truncate).

Un segment está construido de secciones llamadas extents, los cuales son bloques
contiguos de bloques de Oracle. Una vez que los extents existentes no puedan contener
nuevos datos, el segmento obtiene o solicita otro extent. Este proceso de extensión
continúa hasta que no haya más espacio libre en el tablespace o se alcance un máximo
interno por segmento (maxextents). Si un segmento tiene múltiples extents no hay
NINGUNA garantía que que estos sean contiguos.

Para aclarar estas relaciones entre distintos conceptos de la base de datos Oracle,
veamos este esquema:

Databases Tablespaces Datafiles

Users

Esquemas Segmentos Extents


Implicaciones de la claúsula storage

La cantidad de espacio utilizada por un segmento esta determinada por los parámetros de
la claúsula storage al momento de su creación. Si no se utiliza esta claúsula entonces el
segmento, tomará por defecto el storage definido para el tablespace que lo contendrá.

Esta claúsula puede especificarse en los siguientes comandos:

Create table
Create index
Create cluster
Create rollback segment

Los parámetros del storage son:

Initial, define el tamaño en bytes del primer extent.


Next, define el tamaño de los extents subsiguientes.
Pctincrease, es un factor porcentual, por el cual cada subsiguiente extent
irá creciendo geométricamente.
Minextents, el número mínimo de extents a reservar para un objeto, por
defecto es uno.
Maxextents, el número máximo de extents que serán permitidos. En
versiones anteriores a 7.2, el número máximo era 121, ahora se puede indicar
la opción maextents unlimited con lo cual el segmento no tendrá limites de
crecimiento, esto puede tiene su lado negativo, por cuanto como se dijo
anteriormente, no hay garantía de que los extents adicionales estén contiguos
lo cual puede provocar degradamiento del tiempo de respuesta.

Los parámetros initial y minextents no pueden ser cambiados luego de la creación.

Cuando se crea un segmento, adquiere al menos un extent. Este extent será utilizado
para almacenar datos hasta que no haya espacio libre disponible, dentro de cada bloque
también puede reservase espacio libre con la claúsula pctfree, este espacio será utilizado
para actualizaciones de los datos almacenados dentro de cada bloque.

El parámetro pctincrease está diseñado para minimizar el número de extents en tablas en


crecimiento. Un valor DISTINTO DE CERO, puede ser peligroso, ya que causa que cada
extent sucesivo se incremente geométricamente con base al factor especificado.

¿Para qué sirven cada uno de las directivas componentes de la cláusula?

Cuando un objeto es creado debe incluir al menos un extent, la directiva INITIAL


especifica la cantidad en bytes del primer extent que se desea reservar para el objeto,
este espacio se encontrará vacío obviamente en el momento de la creación. La cantidad
en bytes debe ser un múltiplo del tamaño de bloque (4096 bytes), de no ser así el valor
será redondeado al múltiplo más cercano.

El NEXT indica la cantidad de bytes (múltiplos del tamaño de bloque) del siguiente extent
que será alojado cuando el objeto se expanda. PCTINCREASE permite hacer un
incremento porcentual del NEXT de modo dinámico, de manera que si PCTINCREASE es
igual a cero los nuevos extents creados serán exactamente del tamaño especificado en el
NEXT, pero si el PCTINCREASE es de X porcentaje diferente de cero, cada nuevo extent
tendrá un tamaño igual a la suma del tamaño del extent anterior más un incremento del
porcentaje especificado, de este modo los nuevos extents serán más grandes conforme la
tabla sea más grande.

El valor MAXEXTENTS permite acotar la cantidad de extents que conformarán un


segmento, esta directiva es muy práctia para poder controlor el sobre-crecimiento de los
objetos antes de que lleguen al máximo permitido por la base de datos o para detectar
crecimientos desproporcionados y no tomados en cuenta en la fase de diseño.

MINEXTENTS se complementa con el INITIAL, especificando la cantidad de extents que


serán alojados además del INITIAL cuando el objeto sea creado, los nuevos extents serán
creados respetando lo indicado en el NEXT y en el PCTINCREASE.

¿De donde toma Oracle los extents libres para asignarlos a las nuevas tablas y a
las tablas que están creciendo?

Cuando un tablespace es creado, el espacio no usado por las tablas se considera espacio
libre y se administrará como un extent libre, enteramente disponible para la atención de
solicitudes de nuevo espacio. Además cuando un usuario borra un segmento, Oracle
desalojará los extents componentes del segmento y los declarará extents libres.
Luego del borrado, Oracle no recombina extents contiguos aún cuando pertenecieron a un
mismo objeto y ahora se encuentren marcados como libres, Oracle los recombinará solo
si su unión crea un extents suficientemente grande para suplir una solicitud de alojamiento
y esa es la única forma de lograr un extent del tamaño deseado.
Obsérvese que esta política de administración de espacio induce a la existencia de
fragmentación de objetos y fragmentación de espacio libre.

En versiones recientes, si al storage del tablespace se le indica un pctincrease mayor a


cero, Oracle se encarga de conjuntar los extents libres que estén contiguos. También
podemos utilizar el siguiente comando:

alter tablespace DATA coalesce;

¿De que manera utiliza el RDBMS las directivas de la clásula storage?

Cuando el objeto es creado por el usuario, Oracle crea el segmento respectivo en el


diccionario de datos. La indicación de los valores en INITIAL y MINEXTENTS implicará
una importante demanda de espacio fìsico contiguo en los extents libres dentro del
tablespace. En primera instancia el RDBMS buscará en el espacio libre (fragmentado o
no fragmantado) un extent del tamaño especificado en el INITIAL de NO hallarlo
combinará los extents libres contiguos en procura de crear un solo extent del tamaño
solicitado, de no poder construir un extent como el deseado reportará un error de creación
del objeto. Si la acción es exitosa observará el valor del MINEXTENT y continuará
buscando tanto extents libres del tamaño calculado (por NEXT y PCTINCREASE) hasta
que se logre suplir la cantidad de extents solicitada. Los extents creados por causa del
INITAL y el MINEXTENT no tiene por que ser mutuamente contiguos.

Cuando la situación es que la tabla está creciendo, el RDBMS calculará el


PCTINCREASE en base al último extent creado para la tabla y lo adicionará al NEXT,
luego determinará la existencia de un extents suficientemente grande para alojar el
espacio demandado. En todos los casos de búqueda y creación de extents si no se
encuentra un espacio libre del tamaño apropiado se reportará un error de creación del
segmento.

¿Qué implicaciones en el rendimiento tiene la cláusula storage?

Cuando el crecimiento de los segmentos es manejado de modo dinámico por el RDBMS


existe un alto consumo de recursos de procesamiento e I/O, de hecho, la asignación de
nuevos extents es facilmente percibida como un pico de degradación en los tiempos de
respuesta para todos los usuarios en el momento de la ampliación. Una reiterada
sucesión de este evento mostrará un sistema degradado desde la perspectiva del usuario
final. La cláusula storage debe ser ideada de modo que se minimize la presencia de dicho
evento.

Además, el ordenamiento de los registros dentro de bloques contiguos beneficiará el full


scan en tablas y range index en índices.

¿Cuál es el precio que se paga con el uso de la cláusula storage?

Evidentemente no es lógico asignar todo el espacio disponible en un tablespace para que


sea usado por un solo segmento. Se debe pensar que si el espacio libre alojado por los
extents de una tabla es muy grande, transcurrirá mucho tiempo durante el cual dicho
espacio libre será inutilizado.

Además si los extents solicitados para asignar son muy grandes existe menos
probabilidad de localizar grande extensiones de bloques contiguos libres.

Si por otro lado los extents son muy pequeños, el procesamiento dinámico de solicitudes
de extensiónes será más frecuente, y como ya se dijo antes, repercutirá negativamente en
el desempeño del sistema.

¿Es posible modificar la cláusula storage en un momento posterior a la creación de


la tabla?

Si es posible, para ello se utiliza la sentencia ALTER TABLE. Los valores que no pueden
ser modificados son, evidentemente, el INITIAL y el MINEXTENTS.
La modificación de estos valores se aplicará para las futuras extensiones, NO para los
datos ya registrados en la tabla.

¿Existen reglas generales para la aplicación de la cláusula?

Realmente no existen reglas generales, sin embargo es importante el conocimiento de las


características del objetos (finalidad, actualización, inclusión, borrados, etc) antes de su
creación en la base de datos. Debido a que algunas condiciones supuestas en la etapa de
diseño pueden ser refutadas en el ámbito práctico, es importante evaluar periódicamente
el complimiento de las premisas que soportanron la especificación de la directivas de la
cláusula para los objetos de actividad intensiva, una vez iniciada la puesta en producción
de los sistemas.
En general se debe asignar un espacio considerable en términos de INITAL y
MINEXTENS para aquellas tablas que tienen un crecimiento acelerado, considerando un
periodo de 4 meses aproximadamente.

Para las tablas estáticas es útil estimar su tamaño aproximado y reservar desde el inicio
exactamente todo el espacio requerido.

Con la especificación del PCTINCREASE es posible la gestión de grandes extents a


futuro, sin embargo como ya se mencionó esto disminuye la probabilidad de éxito al
encontrar extents suficientemente grandes.
¿Cómo se puede saber el tamaño del último extent asignado a un objeto?

Las vistas USER_TABLES, USER_SEGMENTS y USER_EXTENTS informan sobre los


valores de la cláusula vigente para el objeto, la cantidad de extents y el tamaño de los
extents asignados.

¿Cómo se puede estimar el tamaño de una tabla o índice?

La siguientes fórmulas puede resultar útil para una estimación aproximada:


Para una tabla:
x rows * (5 bytes + y columns * (1 byte + z))
# de bloques = --------------------------------------------------------------------------
(blocksize bytes - 90 bytes) * (1 - PCTFREE/100)
Tamaño = # de bloques * 4096

Para un índice:

x rows * (11 bytes + y + z)


# de bloques = -------------------------------------------------------------------------------
(blocksize bytes - 90 bytes) * (0.75 - PCTFREE/200)

Tamaño = # de bloques * 4096

donde:
x= Cantidad de filas en la tabla.
y=Cantidad de columnas en la tabla o en el índice.
z=El largo promedio de todas las columnas de la tabla o índice (en bytes).
blocksize=tamaño de los bloques de datos = 4096.
PCTFREE = Valor definido para la tabla o índice (Ver adelante en este texto).

¿Para qué sirven las directivas PCTFREE y PCTUSED?

La anterior temática explica la forma en Oracle administra el crecimiento los objetos frente
a la demanda de espacio libre dentro de un tablespace. Además de ello Oracle incorpora
algoritmos relacionados con el manejo del espacio libre en la extensión de los bloques
dentro de cada extent. Dos parámetros de manejo de espacio, el PCTFREE y el
PCTUSED, permiten al diseñador controlar el uso de espacio disponible para inserciones
y actualizaciones de filas en los bloques de datos. Ambos parámetros pueden ser
especificados durante la ejecución de instrucciones de creación o alteración de objetos. El
parámetro PCTFREE es usado para indicar el porcentaje de espacio libre, dentro de un
bloque, que será reservado para actualizaciones de las filas almacenadas en dicho
bloque. El PCTUSED es el parámetro que define la forma de administrar el resto del
espacio libre, indicando el porcentaje mínimo de espacio del bloque que se tenderá a
mantener lleno siempre para cada bloque, visto de otra manera el PCTUSED indicará
cuando un bloque es removido o incluido en la lista de bloques libres, estar en esta lista
significa estar disponible para aceptar nuevas filas.

¿Cómo son usados los parámetros PCTFREE y PCTUSED?

Cuando el objeto es creado o modificado se definen estos parámetros, el PCTFREE es


una cantidad de espacio reservado que define una frontera dentro del bloque, nuevas filas
serán insertadas en el bloques hasta alcanzar esta frontera, momento en el cual el bloque
se considerá lleno. Este espacio reservado se usará solamente para actualizaciones de
las filas que se encuentran almacenadas en el bloque. PCTFREE=20 por ejemplo,
indicará que en cada bloque perteneciente al objeto se reservará un 20 % del espacio
para futuras actualizaciones.

Antes de que la frontera del PCTFREE sea alcanzada, el espacio libre disponible puede
ser usado tanto por la inclusión de nuevas filas como por la actualización de las filas ya
existentes.

Luego de que un bloque llegue a estar lleno, según lo indicado por el PCTFREE, el bloque
no será considerado (será excluido de la free-list) para nuevas inserciones de filas hasta
que el porcentaje de espacio usado llegue a reducirse hasta un valor menor que el
PCTUSED. Cuando este valor sea alcanzado el bloque será nuevamente considerado en
el proceso de inclusión de filas, para ello el bloque se agregará a la free-list del objeto

Header

Espacio
libre

Espacio
usado

La filas son El bloque se El bloque se El ciclo de llenado y


insertadas hasta un encuentra lleno, ya considerará vaciado es repetido
80%, ya que indicó que alcanzó al nuevamente para una y otra vez.
un 20% pctfree. pctfree. Solo se inserción de filas hasta
soportan que el porcentaje de
actualizaciones. uso sea menor que un
40%, vlor del pctused.

¿Qué sucede si el espacio para actualizaciones dentro de un bloque no es


suficiente para acomodar la modificación?

El conocido y molesto efecto de encadenamiento es manifestado en esta situación. Por


ejemplo el encadenamiento entre bloques es común cuando se manejan campos LONG.
Si el largo de fila incluyendo la modificación puede ser suficientemente pequeño como
para guardarse en algún otro bloque, la fila es migrada en su totalidad al nuevo bloque,
sin embargo en el bloque anterior se mantendrá un puntero a la nueva ubicación. El
encadenamiento y migración de filas tiene un efecto negativo desde la perspectiva de I/O.

¿Cómo se seleccionan los valores apropiados de PCTFREE y PCTUSED?

El desempeño de algunas operaciones de base de datos puede verse mejorado mediante


el uso adecuado de los parámetros en mención. Es importante estar familiarizado con las
aplicaciones, en particular es necesario saber cuales operaciones de base datos son
realizadas con más frecuencia en los objetos.

Un bajo valor de PCTFREE puede mejorar el desempeño de full scans, ya que existirá un
promedio mayor de filas por bloque, y será posible leer todas las filas leyendo menos
bloques. Un valor bajo de PCTFREE debe ser usado en tablas query-por excelencia que
carecen de la necesidad de actualización de sus filas.

Un valor alto de PCTFREE disminuye la probabilidad de encadenamiento cuando la filas


sean expandidas. Existe el riesgo de desperdicio de espacio libre.
Recuérdese que el PCTUSED sugiere la inclusión y eliminación de los bloques en las
listas de libres, así un valor bajo de PCTUSED hará que los bloques sean retornados a las
lista de libres con más espacio disponible, ello disminuye también la probabilidad de
encadenamiento.

Un valor alto de PCTUSED reduce la cantidad de espacio libre para los bloques en la
lista, ya que los bloques son retornados a la lista con poco espacio disponible. Un alto
valor de PCTUSED almacena los datos de un modo más eficiente desde la perspectiva de
espacio, pero incrementa la probabilidad de encadenamiento (si no se usa un valor
apropiado de PCTFREE) e incrementa el overhead de administración de las listas de
libres.

Cuando un bloque es retornado a la lista de libres se ubicará al inicio de la lista, por ello
un valor adecuado de PCTUSED permitirá garantizar que el espacio liberado por
DELETEs .
Generalmente los índices no son modificados por ello es recomandable el uso de un bajo
PCTFREE.
Operaciones rutinarias de manejo físico de archivos de Oracle

Cómo cambiar el tamaño de los datafiles

En Oracle 7.2 o superiores, los datafiles existentes pueden ser redimensionados, ya sea
para hacerlos más grandes o más pequeños, si erróneamente se asignó demasiado
espacio para un datafile.

alter tablespace DATA datafile „/f/oracle/data/data01.dbf‟ resize 200M;

También tenemos a partir de esta versión opciones a la hora de crear un datafile para
manejar un crecimiento dinámico:

create tablespace DATA


datafile „/f/oracle/data/data01.dbf‟ size 200M
autoextend on
next 10M
maxsize 250M;

Cómo mover datafiles

Eventualmente necesitamos mover datafiles de un disco a otro por distintas razones, una
puede ser que nos hayamos dado cuenta que la carga de I/O esté desbalanceada o
porque hemos agregado un disco nuevo al equipo, etc.

1. Ponemos el tablespace fuera de linea:


alter tablespace DATA offline;
2. En el sistema operativo movemos el archivo de posición:
mv /f/oracle/data01.dbf /h/oracle/data
3. Alteramos el tablespace para que refleje el cambio:
alter tablespace rename datafile
„/f/oracle/data01.dbf‟ to „/h/oracle/data01.dbf‟;
4. Ponemos el tablespace nuevamente en línea:
Alter tablespace DATA online;
Cómo mover Online Redo Log Files

A veces también se requiere mover los Online redo logs por las mismas razones de
porqué debemos mover un datafile para esto debemos realizar los siguientes comandos:

1. Primero debemos bajar la base de datos:


svrmgrl
connect internal;
shutdown
exit;
2. Luego movemos el online redo log:
mv /f/oracle/redo01.dbf /h/oracle/redo01.dbf
3. Luego montamos la base de datos (sin abrirla), suponiendo que la instancia
se llama DEMO:
svrmgrl
connect internal;
startup mount demo;
alter database rename file
„/f/oracle/redo01.dbf‟ to „/h/oracle/redo01.dbf‟;
4. Luego abrimos (en la misma sesion del svrmgrl) la base de datos:
alter database open;

Cómo mover Control Files

Mover un control file, no será por cuestiones de I/O, podría ser por cuestiones de disco
generalmente, para acerlo debemos realizar los siguientes pasos:

1. Primero debemos bajar la base de datos:


svrmgrl
connect internal;
shutdown
exit;
2. Luego movemos el control file:
mv /f/oracle/ctrl01.ctl /h/oracle/ctrl01.ctl
3. Luego editamos el archivo config.ora:
por ejemplo digamos que el config.ora tenia:
control_files = (/f/oracle/ctr01.ctl, /f/ctrl02.ctl)
entonces ahora quedaría:
control_files = (/h/oracle/ctr01.ctl, /f/ctrl02.ctl)
4. Luego subimos la base de datos nuevamente:
svrmgrl
connect internal;
startup;
exit;
Laboratorio, Instancias y Tablespaces

En esta clase haremos un laborotorio donde aprenderemos básicamente a crear una


instancia y sus tablespaces.

Nota: cambiar XXXX por lo que usted quiera.

1. Entrar a Linux con el usuario oracle, sin password.

2. Abra una sesión de terminal.

3. cd $ORACLE_HOME/dbs

4. cp initDEMO.ora initXXXX.ora

5. Ejecutar en Unix, vi createXXXX.sql, adecúelo al nombre XXXX que usted


haya elegido:

spool createdbTEST
set echo on
connect INTERNAL/manager
startup nomount pfile=$ORACLE_HOME/dbs/initTEST.ora
CREATE DATABASE TEST
LOGFILE '$ORACLE_HOME/dbs/redoTEST01.log' SIZE 1024K,
'$ORACLE_HOME/dbs/redoTEST02.log' SIZE 1024K
MAXLOGFILES 32
MAXLOGMEMBERS 2
MAXLOGHISTORY 1
DATAFILE '$ORACLE_HOME/dbs/systemTEST01.dbf' SIZE 50M
MAXDATAFILES 254
MAXINSTANCES 1
CHARACTER SET WE8ISO8859P1
NATIONAL CHARACTER SET WE8ISO8859P1;

ALTER DATABASE
DATAFILE '$ORACLE_HOME/dbs/systemTEST01.dbf' AUTOEXTEND ON;

CREATE ROLLBACK SEGMENT SYSROL


TABLESPACE "SYSTEM"
STORAGE (INITIAL 100K NEXT 100K);

ALTER ROLLBACK SEGMENT "SYSROL" ONLINE;

CREATE TABLESPACE RBS


DATAFILE '$ORACLE_HOME/dbs/rbsTEST01.dbf' SIZE 12M
DEFAULT STORAGE ( INITIAL 1024K NEXT 1024K MINEXTENTS 2 MAXEXTENTS 121
PCTINCREASE 0);

ALTER DATABASE DATAFILE '$ORACLE_HOME/dbs/rbsTEST01.dbf' AUTOEXTEND ON;


ALTER TABLESPACE SYSTEM
DEFAULT STORAGE ( INITIAL 100K NEXT 100K MINEXTENTS 1 MAXEXTENTS 300
PCTINCREASE 1);

CREATE TABLESPACE USERS


DATAFILE '$ORACLE_HOME/dbs/usersTEST01.dbf' SIZE 3M
DEFAULT STORAGE ( INITIAL 50K NEXT 50K MINEXTENTS 1 MAXEXTENTS 121
PCTINCREASE 1);

ALTER DATABASE DATAFILE '$ORACLE_HOME/dbs/usersTEST01.dbf' AUTOEXTEND ON;

CREATE TABLESPACE TEMP


DATAFILE '$ORACLE_HOME/dbs/tempTEST01.dbf' SIZE 20M
DEFAULT STORAGE ( INITIAL 100K NEXT 100K MINEXTENTS 1 MAXEXTENTS 121
PCTINCREASE 0) TEMPORARY;

ALTER DATABASE DATAFILE '$ORACLE_HOME/dbs/tempTEST01.dbf' AUTOEXTEND ON;

CREATE TABLESPACE INDX


DATAFILE '$ORACLE_HOME/dbs/indxTEST01.dbf' SIZE 10M
DEFAULT STORAGE ( INITIAL 50K NEXT 50K MINEXTENTS 1 MAXEXTENTS 121
PCTINCREASE 1);

ALTER DATABASE DATAFILE '$ORACLE_HOME/dbs/indxTEST01.dbf' AUTOEXTEND ON;

CREATE TABLESPACE OEM_REPOSITORY


DATAFILE '$ORACLE_HOME/dbs/oemrepTEST01.dbf' SIZE 5M
AUTOEXTEND ON NEXT 25M MAXSIZE 80M
MINIMUM EXTENT 128K
DEFAULT STORAGE ( INITIAL 128K NEXT 128K MINEXTENTS 1
MAXEXTENTS UNLIMITED PCTINCREASE 0);

CREATE PUBLIC ROLLBACK SEGMENT RB0 TABLESPACE RBS


STORAGE (INITIAL 100K NEXT 250K);

CREATE PUBLIC ROLLBACK SEGMENT RB1 TABLESPACE RBS


STORAGE (INITIAL 100K NEXT 250K);

ALTER ROLLBACK SEGMENT "RB0" ONLINE;

ALTER ROLLBACK SEGMENT "RB1" ONLINE;

alter user sys temporary tablespace TEMP;


alter user system temporary tablespace TEMP;

@$ORACLE_HOME/rdbms/admin/catalog.sql;
@$ORACLE_HOME/rdbms/admin/catexp7.sql
@$ORACLE_HOME/rdbms/admin/catproc.sql
@$ORACLE_HOME/rdbms/admin/caths.sql

connect system/manager
@$ORACLE_HOME/sqlplus/admin/pupbld.sql
connect INTERNAL/manager

alter rollback segment "SYSROL" offline;

spool off

6. Ejecutar en Unix vi initXXXX.ora, cambiar lo que se muestra en negrita en


el archivo initDEMO.ora:

#
# $Header: init.ora 05-jun-97.14:56:46 hpiao Exp $
#
# Copyright (c) 1991, 1997 by Oracle Corporation
# NAME
# init.ora
# FUNCTION
# NOTES
# MODIFIED
# hpiao 06/05/97 - fix for 803
# glavash 05/12/97 - add oracle_trace_enable comment
# hpiao 04/22/97 - remove ifile=, events=, etc.
# alingelb 09/19/94 - remove vms-specific stuff
# dpawson 07/07/93 - add more comments regarded archive start
# maporter 10/29/92 - Add vms_sga_use_gblpagfile=TRUE
# jloaiza 03/07/92 - change ALPHA to BETA
# danderso 02/26/92 - change db_block_cache_protect to _db_block_cache_p
# ghallmar 02/03/92 - db_directory -> db_domain
# maporter 01/12/92 - merge changes from branch 1.8.308.1
# maporter 12/21/91 - bug 76493: Add control_files parameter
# wbridge 12/03/91 - use of %c in archive format is discouraged
# ghallmar 12/02/91 - add global_names=true, db_directory=us.acme.com
# thayes 11/27/91 - Change default for cache_clone
# jloaiza 08/13/91 - merge changes from branch 1.7.100.1
# jloaiza 07/31/91 - add debug stuff
# rlim 04/29/91 - removal of char_is_varchar2
# Bridge 03/12/91 - log_allocation no longer exists
# Wijaya 02/05/91 - remove obsolete parameters
#
##############################################################################
# Example INIT.ORA file
#
# This file is provided by Oracle Corporation to help you customize
# your RDBMS installation for your site. Important system parameters
# are discussed, and example settings given.
#
# Some parameter settings are generic to any size installation.
# For parameters that require different values in different size
# installations, three scenarios have been provided: SMALL, MEDIUM
# and LARGE. Any parameter that needs to be tuned according to
# installation size will have three settings, each one commented
# according to installation size.
#
# Use the following table to approximate the SGA size needed for the
# three scenarious provided in this file:
#
# -------Installation/Database Size------
# SMALL MEDIUM LARGE
# Block 2K 4500K 6800K 17000K
# Size 4K 5500K 8800K 21000K
#
# To set up a database that multiple instances will be using, place
# all instance-specific parameters in one file, and then have all
# of these files point to a master file using the IFILE command.
# This way, when you change a public
# parameter, it will automatically change on all instances. This is
# necessary, since all instances must run with the same value for many
# parameters. For example, if you choose to use private rollback segments,
# these must be specified in different files, but since all gc_*
# parameters must be the same on all instances, they should be in one file.
#
# INSTRUCTIONS: Edit this file and the other INIT files it calls for
# your site, either by using the values provided here or by providing
# your own. Then place an IFILE= line into each instance-specific
# INIT file that points at this file.
###############################################################################

# replace DEFAULT with your database name


db_name=XXXX

db_files = 80 # SMALL
# db_files = 400 # MEDIUM
# db_files = 1000 # LARGE

db_file_multiblock_read_count = 8 # SMALL
# db_file_multiblock_read_count = 16 # MEDIUM
# db_file_multiblock_read_count = 32 # LARGE

db_block_buffers = 100 # SMALL


# db_block_buffers = 550 # MEDIUM
# db_block_buffers = 3200 # LARGE

shared_pool_size = 3500000 # SMALL


# shared_pool_size = 5000000 # MEDIUM
# shared_pool_size = 9000000 # LARGE

log_checkpoint_interval = 10000

processes = 50 # SMALL
# processes = 100 # MEDIUM
# processes = 200 # LARGE

parallel_max_servers = 5 # SMALL
# parallel_max_servers = 4 x (number of CPUs) # MEDIUM
# parallel_max_servers = 4 x (number of CPUs) # LARGE

log_buffer = 8192 # SMALL


# log_buffer = 32768 # MEDIUM
# log_buffer = 163840 # LARGE

sequence_cache_entries = 10 # SMALL
# sequence_cache_entries = 30 # MEDIUM
# sequence_cache_entries = 100 # LARGE

sequence_cache_hash_buckets = 10 # SMALL
# sequence_cache_hash_buckets = 23 # MEDIUM
# sequence_cache_hash_buckets = 89 # LARGE

# audit_trail = true # if you want auditing


# timed_statistics = true # if you want timed statistics
max_dump_file_size = 10240 # limit trace file size to 5 Meg each

# Uncommenting the line below will cause automatic archiving if archiving has
# been enabled using ALTER DATABASE ARCHIVELOG.
# log_archive_start = true
# log_archive_dest = disk$rdbms:[oracle.archive]
# log_archive_format = "T%TS%S.ARC"

# If using private rollback segments, place lines of the following


# form in each of your instance-specific init.ora files:
# rollback_segments = (name1, name2)

# If using public rollback segments, define how many


# rollback segments each instance will pick up, using the formula
# # of rollback segments = transactions / transactions_per_rollback_segment
# In this example each instance will grab 40/10 = 4:
# transactions = 40
# transactions_per_rollback_segment = 10

# Global Naming -- enforce that a dblink has same name as the db it connects to
global_names = TRUE

# Edit and uncomment the following line to provide the suffix that will be
# appended to the db_name parameter (separated with a dot) and stored as the
# global database name when a database is created. If your site uses
# Internet Domain names for e-mail, then the part of your e-mail address after
# the '@' is a good candidate for this parameter value.

# db_domain = us.acme.com # global database name is db_name.db_domain

# FOR DEVELOPMENT ONLY, DEFAULT TO SINGLE-PROCESS


# single_process = TRUE

# FOR DEVELOPMENT ONLY, ALWAYS TRY TO USE SYSTEM BACKING STORE


# vms_sga_use_gblpagfil = TRUE

# FOR BETA RELEASE ONLY. Enable debugging modes. Note that these can
# adversely affect performance. On some non-VMS ports the db_block_cache_*
# debugging modes have a severe effect on performance.

#_db_block_cache_protect = true # memory protect buffers


#event = "10210 trace name context forever, level 2" # data block checking
#event = "10211 trace name context forever, level 2" # index block checking
#event = "10235 trace name context forever, level 1" # memory heap checking
#event = "10049 trace name context forever, level 2" # memory protect cursors

# define parallel server (multi-instance) parameters


#ifile = ora_system:initps.ora

# define two control files by default


control_files = (control XXXX1, XXXX2)
control

# Uncomment the following line if you wish to enable the Oracle Trace product
# to trace server activity. This enables scheduling of server collections
# from the Oracle Enterprise Manager Console.
# Also, if the oracle_trace_collection_name parameter is non-null,
# every session will write to the named collection, as well as enabling you
# to schedule future collections from the console.

# oracle_trace_enable = TRUE

7. En el prompt de Unix ejecutar:

ORACLE_SID=XXXX
export ORACLE_SID

8. Ejecutar svrmgrl

connect internal
@createXXXX.sql

9. Si no hubo problemas, pruebe dentro del svrmgrl

shutdown
startup

10. Salga del svrmgrl, en Unix ejecute, ls -la *xxxx* , observe todos los distintos archivos
que fueron creados, tales como datafiles, control files y redo logs.

11. En Unix ejecute, ps -ef | grep ora, observe los "background process" que están
corriendo.
Laboratorio, errores, cambiar tamaño de datafiles, mover
datafiles, script genéricos.

Provocar un error irrecuperable....

1. Conectarse a Unix con el usuario Oracle y sin password.


2. Ejecutar: mv systemXXXX01.dbf XXXXsystem01.dbf
3. Ejecutar en el svrmgrl

Connect internal
Startup

Ver los errores que aparecen......

Shutdown abort
exit
4. Ejecutar: mv XXXXsystem01.dbf systemXXXX01.dbf

Mover datafiles, cambio de tamaño y agregar datafiles

5. Ejecutar: mkdir new_disc


Ponemos el tablespace fuera de linea:
alter tablespace users offline;
En el sistema operativo movemos el archivo de posición:
mv $ORACLE_HOME/dbs/usersXXXX01.dbf (en la misma linea->)
$ORACLE_HOME/dbs/new_disc/usersXXXX01.dbf
Alteramos el tablespace para que refleje el cambio:
sqlplus system/odin o svrmgrl y connect internal
alter tablespace USERS rename datafile
'$ORACLE_HOME/dbs/usersXXXX01.dbf ' to
'$ORACLE_HOME/dbs/new_disc/usersXXXX01.dbf';
Ponemos el tablespace nuevamente en línea:
alter tablespace USERS online;

6. En el laboratorio del dia de ayer creamos un tablespace USERS con un tamaño de 3


megas, si desea verifíquelo en Unix con el comando ls -la users*
7. Dentro del svrmgrl ejecute: alter tablespace USERS datafile
„$ORACLE_HOME/dbs/new_disc/usersXXXX01.dbf‟ resize 10M;
con esto "estiramos" el datafile de 3M a 10M.....
8. Ahora bien, si en el disco actual no hubiera más espacio disponible, entonces
tendríamos que agregar un datafile más a este tablespace: alter tablespace USERS
add datafile '$ORACLE_HOME/dbs/new_disc/users02.dbf' size 1M;

Varios scripts

9. svrmgrl y connect internal

show parameters

observe la cantidad de parámetros posibles que maneja la base de datos, dele una
mirada y trate de imaginarse para que sirve cada uno.....

select tablespace_name, segment_name, status from dba_rollback_segs;


select tablespace_name from dba_tablespaces;
select tablespace_name, sum(bytes)/1024/1024 from dba_data_files group by
tablespace_name;
select tablespace_name, file_name, bytes/1024/1024 from dba_data_files;
select username from dba_users;
select username, default_tablespace, temporary_tablespace, profile from dba_users;
select * from dba_profiles;

de los anteriores scripts, observe cada resultado, piense en la utilidad que podrían tener
eventualmente.....

10. En Unix ejecute: sqlplus system/odin


11. Ahora cree los siguientes usuarios:

Create user RH
Identified by RH
Default tablespace users
Temporary tablespace temp
Quota unlimited on users;

Create user fernando


Identified by fernando
Default tablespace users
Temporary tablespace temp
Quota unlimited on users;

Create user pedro


Identified by pedro
Default tablespace users
Temporary tablespace temp
Quota unlimited on users;
9. En unix ejecute: sqlplus prueba/prueba
10. Ahora creemos una tabla de ejemplo:

Create table emp(


Deptno number(5),
Empno number(5),
Name varchar2(30),
Salary number(11,2),
Mgr_no number(5),
Birth_date date);

Alter table emp


Add constraint pk_emp
Primary key(empno);

Utilizando la sentencia insert de SQL, metale algunos datos de prueba a esta tabla.

11. Ahora conectese en sqlplus como system/odin:

Create role gerente;


Create role empleado;
Grant gerente to fernando;
Grant empleado to pedro;

12. Ahora conectese en sqlplus como usuario RH/RH:

Grant select, insert, update, delete on emp to gerente;


Grant select on emp to empleado;

13. Ahora conectese como fernando/fernando en sqlplus y trate de consultar, borrar o


insertar datos nuevos en la tabla RH.emp

14. Luego conectese como pedro/pedro en sqlplus y trate de consultar, borrar o insertar
datos en la tabla RH.emp
Afinamiento del SQLsad

Una aplicación que esté muy bien diseñada en su modelo de base de datos, que corra en
una base de datos donde hayamos tomado todas las precauciones posibles, puede ser
que tenga problemas de rendimiento a pesar de todo debido a que los programadores
escribieron el SQL sin tomar en cuenta ciertas condiciones para un desempeño óptimo.

En una base de datos relacional, la localización física de los datos no es tan importante
como la localización lógica dentro del diseño de la aplicación. Sin embargo la base de
datos tiene que encontrar los datos para poder devolverlos a un usuario que esté
haciendo una consulta. La llave para afinar el SQL es minimizar la ruta de búsqueda que
la base de datos utiliza para encontrar los datos.

Para todas las tablas en Oracle, cada fila tiene un RowId asociado. El RowID contiene
información acerca de la localización física de la fila (archivo, bloque y fila dentro del
bloque).

Cuando un query sin claúsula where es ejecutado, la base de datos deberá realizar un full
scan table, leyendo cada uno de los bloques de la tabla. Para hacer esto la base de datos
localiza el primer extent de la tabla y entonces lee secuencialmente a través de todos los
extents de dicha tabla. Para tablas grandes esto puede significar una gran cantidad de
tiempo.

Cuando se consultan filas específicas, la base de datos podría utilizar un índice para
ayudar a acelerar la búsqueda las filas deseadas. Un índice mapea valores lógicos de
una tabla en sus respectivos RowId's, los cuales a su vez mapean la ubicación física. Los
índices pueden ser únicos o no únicos.

Podemos crear un índice con varias columnas. A este se le llama un índice concatenado,
y será utilizado si al menos la primer columna indexada es mencionada en el where.

Por ejemplo supongamos un índice con tres columnas:

create index city_st_zip_ndx


on employee(city, state, zip)
tablespace indexes;

si hacemos un query como:

select * from employee


where state = 'NJ';

el índice no será utilizado, debido a que la primer columna(City) no es usada en la


claúsula where. Si los usuarios, frecuentemente utilizan búsquedas por state, entonces el
índice debería ser recreado poniendo la columna state de primero.

Ahora bien, ¿cómo saber la ruta de acceso que utilizará la base de datos para realizar
una consulta? Para esto tenemos en SQL*Plus el seteo "set autotrace on", el cual nos
permite luego de ejecutar una consulta ver si se utiliza o no algún índice y en que forma
está siendo utilizado.

Para poder utilizar esta facilidad debemos ejecutar primero un script que se llama
UTLXPLAN.sql, el cual normalemente se encuentra en el directorio
$ORACLE_HOME/rdbms/admin.

Por ejemplo el query:

Select * from employee


Where city > 'Y%';

produciría el siguiente resultado:

-------------------------------
SELECT STATEMENT
TABLE ACCESS BY ROWID EMPLOYEE
INDEX RANGE SCAN CITY_ST_ZIP_NDX

Para leer el plan, lea el orden de las operaciones desde adentro hacia fuera de la
jerarquía. En el caso de ejemplo nos dice que hace un "range scan" del índice, lo cual
una búqueda dentro de un rango de valores, lo cual es mejor que leer toda la tabla.

Cuando se evalúan los resultados del plan, deberíamos asegurarnos que los índices más
selectivos (o sea los más cercanos a valores únicos) sean utilizados por el query. Si se
utiliza un índice no muy selectivo, estaríamos forzando a la base de datos a realizar
lecturas innecesarias para resolver la consulta.

Si la aplicación está orientada a trabajos en lotes (data-warehouse), debemos enfocarnos


a mejorar el tiempo total para completar la transaccion. Mejorar el rendimiento total de
una transacción requiere realizar "full table scans" en vez de índices. Dado que los full
table scan pueden utilizar el Parallel Query Option, podríamos involucrar mayores
recursos computacionales en la ejecución de la consulta, mejorando con esto el
rendimiento.

Afinando sintaxis

SQL es un lenguaje declarativo, de modo que los queries pueden ser escritos de muchas
maneras. Aunque se pueden obtener resultados idénticos a partir de un número variado
de queries, el tiempo de ejecución de cada uno puede variar dramáticamente. Para
ilustrar este concepto, digamos que tenemos una pequeña tabla de empleados con sólo
15 filas y un índice por sexo y fecha de contratación. Si ejecutamos el siguiente query:

Select emp_name
From emp
Where
Sex = 'F' and hiredate between sysdate -90 and sysdate;

Debido a que la tabla tiene sólo 15 filas, la más eficiente manera de realizar esta consulta
sería realizando un full-table scan. Sin embargo, Oracle lo realizaría (talvez) recorriendo
los índices, aunque hubiera sido más rápido el full-table scan. Esto causa I/O adicional
para leer el árbol del índice y luego accesar las filas de la tabla.

Aunque este ejemplo es muy simplista, sirve para ilustrar el concepto de que el tiempo de
ejecución del SQL es muy dependiente de la estructura del query y de los índices.

Consideraciones de costo
El primer paso para afinar el Oracle SQL es comparar el costo relativo de cada acceso
SQL.

Costo Tipo de Operación


1 Una fila por Row ID
2 Una fila por join de cluster
3 Una fila por hash cluster con llave primaria o índice único.
4 Una fila por llave primaria o índice único
5 Join de cluster
6 Llave de hash cluster
7 Llave de cluster indexada
8 Índice de múltiples columnas
9 Índice una sóla columna
10 Búsqueda con límites en columnas indexadas
11 Búsqueda sin límites en columnas no indexadas

Como vemos la forma más rapida de recuperar una fila es conociendo su RowID.
Algunas aplicaciones han caído en el error de utilizar búsquedas internas utilizando el
RowId, pero NO EXISTE NINGUNA garantía de que una fila esté siempre en el mismo
RowID, ya que como recordarán una fila puede ser migrada en cualquier momento por
falta de espacio, con lo que el uso de RowID se inutiliza.

Por otro lado el mayor costo es un full-table scan. Para tablas pequeñas es lo más
deseable, pero puede causar verdaderos dolores de cabeza cuando un full-table scan se
realiza sobre una tabla grande. Por lo tanto evitar los full-table scan es la primera
consideración a la hora de realizar afinamiento.

Sin embargo, debe considerarse otra situación, por ejemplo para un query muy complejo,
un full-table scan podría ser lo más eficiente, pero esto es hecho en contra de "otros" SQL
en el sistema que puedan estar corriendo en ese momento; entonces debemos
preguntarnos ¿afinamos un query específico? o ¿afinamos toda la base de datos como un
conjunto?. La respuesta a estas preguntas no es sencilla, debido a que cada sentencia
SQL debe ser afinada individualmente, pero este afinamiento NO debe realizarse a
expensas de otros queries en la base de datos.
Operadores Booleanos en SQL
Desde que empezamos a estudiar Informática se nos ha enseñado que entre más
compacto sea un programa, mejor será su ejecución. En SQL esto no siempre es lo
mejor, vemos el siguiente caso:

select
student_name
from
student
where
(student_nbr = :host_student
or
:host_student is null)
and
(social_security_nbr = :host_social
or
:host_social is null);

Como pueden ver este query está formulado para que funcione si el usuario digita el
student_nbr o el social_security_nbr o ambos. Esta es una manera muy útil de escribir el
SQL ya que la aplicación utiliza el mismo código. Desde el punto de vista de
programación es muy conciso y claro. Desafortunadamente no se ejecuta eficientemente.

Por ejemplo este query deberia reformularse como:

Select student_name
From student
Where student_nbr = :host_student
And :host_student is not null
And :host_social is null
UNION
Select student_name
From student
Where social_security_nbr = :host_social
And :host_social is not null
And :host_student is null
UNION
Select student_name
From student
Where student_nbr = :host_student
And social_security_nbr = :host_social
And :host_social is not null
And :host_student is not null
UNION
Select student_name
From student
Where :host_social is null
And :host_student is null
;
Como podemos ver, el query original ha sido particionado en queries separaos y
concatenados con el operardor UNION de SQL. Sólo el cuarto query, en caso de que
ambos valores en la forma sean nulos provocará un full-scan table, los otros tres utilizarán
los índices por student_nbr o social_security_nbr.

Aunque reescribir este query de esta manera parece un gran esfuerzo, SI este query es
para una aplicación en línea que es ejecutada MILES de veces al dia, la ganancia en el
rendimiento bien vale la pena.

Como reglas comunes podemos mencionar las siguientes para que nuestras consultas
sean lo más eficientes posible:

NUNCA haga un cálculo sobre una columna indexada


(ej. WHERE salario * 5 > :mi_variable)
SIEMPRE que sea posible utilize UNION en vez de condiciones OR.
Evite el uso de NOT IN or HAVING en la claúsula WHERE. En lugar utilize la
claúsula NOT EXISTS.
Siempre especifique valores numéricos en forma numérica y valores carácter
en forma carácter, o sea NO MEZCLE tipos de datos.
Evite especificar NULL en una columna indexada.
Evite el LIKE si se puede utilizar el =.
Si su base de datos utiliza el optimizador basado en reglas (rule-based) , la
posición de las tablas en el WHERE es utilizado para escoger la tabla que va a
manejar el query. Siempre ponga la tabla que más filas va a traer de primero.
Evite utilizar sub-queries cuando se puede hacer lo mismo con un JOIN.
Utilize la función decode para minimizar el número de veces que una tabla es
seleccionada.
Para "apagar" un índice que no quiere utilizar, concatene un string nulo a la
columna indexada (ej. name||'') o agregele un cero si la columna es numérica
(ej. salario+0).
Si su consuta retorna más del 20% de las filas en la tabla, utilize un full-scan
table en lugar de un index-scan.
SIEMPRE utilize alias de las tablas cuando referencia las columnas (ej.
student.name)
Afinando los índices en SQL
Como regla genera, los índices siempre mejorar el rendimiento de una consulta en la base
de datos. En Oracle, los índices se utilizan para acelerar las consultas y para pre-ordenar
conjuntos pequeños de datos sin generar un sort interno cuando se utiliza el order by.

Para que se utilize un índice, el optimizador de SQL debe reconocer que una columna
tiene valor válido para buscar en el índice. A esto se le conoce como predicados de
búsqueda, por ejemplo:

Predicados válidos

select * from emp where emp_no = 123;


select * from emp where dept_no = 10;

Predicados inválidos

select * from emp where emp_no = "123";


select * from emp where salary * 2 < 5000;
select * from emp where dept_no != 10;

Siempre que ocurra una transformación sobre un campo, Oracle no podrá utilizar un
índice para esta columna.

Hay ocasiones en que cuando programamos la aplicación podemos presumir cuando


vamos a necesitar leer muchos datos y cuando pocos. Por ejemplo si tenemos la misma
tabla student con un campo que tiene dos valores posibles ('GRADUADOS',
'NOGRADUADOS'). Supongamos que en la base de datos tiene un 90 % de estudiantes
sin graduar y un 10% de graduados, Oracle no conoce esta distribución de antemano, asi
que si existiera un índice sobre este campo, y realizamos una consulta donde el where
especifica si el estudiante está graduado, Oracle utilizará el índice, lo cual está bien
porque sólo hay un 10% de estudiantes graduados; pero en otra consulta o reporte talvez
queramos traer sólo los estudiantes no graduados, en este caso Oracle igual utilizará el
índice, pero no será eficiente pues recuperará el 90% de los estudiantes, en este caso
debemos anular el índice concatenando un valor null en el where:

Select * from student where student_leve||'' = 'NOGRADUADO";

Índices concatenados

Un índice concatenado se crea basado en múltiples columnas. Este tipo de índice puede
acelerar grandemente una consulta cuando todas las columnas especificadas en el where
pertenecen a un índice.

Por ejemplo, veamos el siguiente índice:

Create idnex idx1


On student (student_level, major, laste_name) ascending;
Este índice puede ser utilizado para acelar búsquedas que hagan referencia a ambos
campos, student_level y major:

Select student_level
From student
Where student_level = 'NOGRADUADO'
And major = 'computer science';

Sin embargo, algunos queries que utilizan uno u otro campo, no serán capaces de utilizar
este índice concatenado; en el siguiente ejemplo, sólo el campo major es referenciado en
el query:

Select *
From student
Where major = 'computer science';

En este ejemplo, aunque el major está en el índice, está como segunda columna, por lo
que Oracle concluirá que el índice no es utilizable.

Veamos este otro ejemplo:

Select last_name
From student
Where student_level = 'PLEBE'
Order by last_name;

En este caso, debido a que el campo student_level es el pimer campo del índice, la
primera parte del índice puede se leída, y el optimizador de SQL invocará un index scan.

Índices Bitmap
A partir de Oracle 7.3, podemos crear índices bitmap, los cuales son una muy buena
opción para columnas de datos con muy pocos valores únicos, como regla general menor
a 20. El índice bitmap consume hasta 80 veces menos espacio que un índice b-tree y
provee un mejor tiempo de respuesta.

El operador NOT
El operador NOT causa que la utilización de un índice sea OBVIADA causando un full-
scan table en el siguiente ejemplo:

Select * from student


Where student_level = 'NOGRADUADO'
And major != 'computer science';

Aquí la condición NOT produce un full-scan table no deseado.

Como hemos visto, muchas veces podemos provocar full-scan tables sin darnos cuenta o
imaginarnoslo siquiera remotamente, para esto Oracle provee una herramienta muy útil
que es el EXPLAIN PLAN, el cual veremos en detalle.
EXPLAIN PLAN

Como hemos mencionado en clases anteriores antes de poder utilizar el explain plan
debemos crear bajo el usuario correspondiente la tabla plan_table, cuyo script de creación
está en $ORACLE_HOME/rdbms/admin y se llama utlxplan.sql.

Veamos un ejemplo de cómo utilizar esta facilidad:

explain plan
set statement_id = 'TEST1' for
select * from student
where student_nbr = 10;

Es importante notar que al ejecutar en sqlplus este comando, el query no se ejecuta sólo
se valida contra la base de datos y se determina el plan de ejecución, el query como tal no
es ejecutado. Esto es importante para afinar querys sin esperar los resultados.

Luego de haber llenado la tabla plan_table debemos ejecutar un query como el


siguiente:

Set pages 9999


Select lpad(' ', 2*(level-1)) || operation operation,
Options,
Object_name,
Position
From plan_table
Start with id=0
And statement_id='TEST1'
Connect by prior id = parent_id;

como resultado de este query podemos ver si la consulta utiliza o no indices y en que
forma, en este caso en particular utiliza la llave primaria que ha por student_nbr.

Aunque el plan_table es útil para determinar la ruta de acceso a los datos, por si sólo no
cuenta toda la historia. La configuración de los datos es también una consideración.
Mientras que el optimizador de SQL conoce el número de filas de cada tabla (la
cardinalidad) y la presencia de índices sobre los campos, el optimizador de SQL NO
conoce ciertos factores como el número esperado de filas retornadas de cada consulta.

Existe otra herramienta, el trace de SQL, que muestra en detalle todos los recursos
utilizados o consumidos durante la ejecución de una consulta, tales como el número de
accesos de I/O requeridos para satisfacer la consulta, el tiempo de CPU utilizado, etc.
Esta la veremos más adelante.

Los posibles métodos de acceso que podríamos ver en un explain plan serían:

AND-EQUAL, indica que las tablas están siendo "joineadas" y que Oracle será
capaz de utilizar los valors de los índices para hacer join de las filas.
CONCATENATION, indica una operación UNION.
COUNTING, indica el uso de la función count de SQL.
FILTER, indica que la claúsula where está removiendo filas no deseadas del
conjunto resultante.
FIRST ROW, indica que se ha declarado un cursor para la consulta
FOR UPDATE, indica que las filas retornadas serán bloqueadas.
INDEX (UNIQUE), indica que se utiliza un valor específico de llave.
INDEX (RANGE SCAN), indica que se busca por rangos en un índice,
usualmente al utilizar BETWEEN, LESS THAN o GREATHER THAN.
INTERSECTION, indica un conjunto solucion para dos tablas joineadas.
MERGE JOIN, indica que se utilizaron dos conjuntos resultantes para resolver
la consulta.
NESTED LOOPS, indica que la última operación seá realizada n veces, una
por cada operación precedente.
PROJECTION, indica que sólo ciertas columnas de una fila seleccionada serán
retornadas
SORT, indica un ordenamiento, en memoria o en el tablespace TEMP.
TABLE ACCESS (ROWID), indica que una fila es accesada por ROWID.
TABLE ACCESS (FULL), este es un full-table scan y es el más lento de todos a
menos que la tabla sea muy pequeña.
UNION, indica que probablemente se utilizó la claúsula DISTINCT de SQL.
VIEW, indica que una vista de SQL está involucrada en la consulta.

Optimizadores de Oracle

Oracle ofrece dos métodos para afinar SQL, si se está usando Oracle 7.2 o superior,
podemos utilizar el optimizador basado en costos, mientras que para versiones anteriores
lo aconsejable es utilizar el optimizador basado en reglas.

Cuando se utiliza en optimizador basado en reglas, el indexado de las talbas y el ORDEN


de las claúsulas dentro de cada sentencia SQL controlan las rutas de acceso. El
optimizador basado en costos automáticamente determina la ruta de ejecución más
eficiente y el programador puede pasar ciertos hints para altera la ruta de acceso ya que
conoce de antemano los resultados.

Por default Oracle se instala con el parámetro opimizer_mode=CHOOSE, esto le indica a


Oracle favorecer el optimizador basado en costos siempre y cuando las tablas
involucradas en la consulta tengan estadísticas. Las estadísticas son creadas con el
comando ANALYZE TABLE. Esto tiene varios problemas potenciales como son:

1. Por ejemplo en una consulta con tres tablas, si una o más tienen
estadísitcas, Oracle utilizará el optimizador basado en costos y ejecutará un
analyze tabla para las otras tablas que no tienen estadísiticas en tiempo de
ejecución retardando enormente esa consulta en particular.
2. Si, el DBA no ejecuta regularmente el analyze table, las estadísitcas
estarán desactualizadas y provocarán resultados aleatorios.

En general el optimizador basado en costos es la mejor opción pero las estadísticas


deben actualizarse regularmente. Para hacer esto podríamos ejecutar regularmente el
siguiente script:

Spool runstat.sql
Select
'analyze table ' || owner || '.' || table_name || '
estimate statistics sample 20%;'
from
dba_tables
where
owner not in ('SYS','SYSTEM');

select
'analyze index '|| owner || '.' || index_name || '
compute statistics;'
from
dba_indexes
where
owner not in ('SYS','SYSTEM');

spool off
@runstat

Hints
Hay ocasiones en que las que el optimizador de Oracle decida no es lo mejor. Para esto
tenemos a disposición una serie de hints, los cuales son mayormente útiles cuando
tenemos alguna idea del comportamiento de la aplicación y los datos.

En forma genérica podriamos hacer que para una aplicación o sesión en particular
cambiemos la forma de trabajar del optimizador:

Alter session set optimizer_goal = ALL_ROWS;


o
Alter session set optimizer_goal = FIRST ROWS;

el primero le indica al optimizador que lo que queremos es que traiga TODO lo antes
posible, en cambio el segundo le indica que traiga la primera fila lo antes posible.
Normalmente el primero se utilizaría para procesos en lotes (generalmente nocturnos) y la
segunda para aplicaciones en línea.

Además para una query en particular podemos indicarle al optimizador hints específicos
utilizando el siguiente ejemplo:

select /*+ ALL_ROWS /* customer_name from customer;


en vez de ALL_ROWS podemos utilizar:

ALL_ROWS, provee el mejor rendimiento global y un consumo menor de


recursos, para procesos en lotes.
FIRST_ROWS, provee el mejor tiempo de respuesta en línea.
INDEX(table_name index_name), obliga al optimizador a utilizar un índice
en particular. Por ejemplo: select /*+ INDEX(PK_PR_CREDITOS
PR_CREDITOS) */ monto_credito from pr_creditos;
RULE, indica que se utilize el optimizador basado en reglas, recuerde que
el where debe estar en orden con respecto a los índices y la tabla más
pequeña debe estar a la derecha del from.

hay muchas opciones más no utilizadas frecuentemente.

Debido a que los hints son codificados en las consultas como comentarios, el SQL no le
indicará un error si un hint está escrito incorrectamente.

Cuando utilize ALTER SESSION SET OPTIMIZER_GOAL, es importante recordar que


este no tendrá efecto para SQL que ya esté en el shared pool de SQL, si se desea se
puede ejecutar el comando ALTER SYSTEM FLUSH SHARED POOL para que regenere
los SQL en el shared pool.

Afinando Sub-queries

Siempre que sea posible, el uso de un sub-query debe ser evitado en Oracle. En la
mayoría de los casos, el subquery puede ser remplazado por un JOIN estándar. Sin
embargo hay circunstancias en las que el uso de un sub-query es inevitable.

Como sabemos, Oracle en un update o delete sólo permite UNA tabla, como
consecuencia, la única manera de especificar valores de otra tabla es haciendo un
subquery, por ejemplo:

Update table1
Set attr = 'Y'
Where key in (select key from table2);

Hemos dicho antes que cada quien puede escribir un query como le parezca y tengamos
30 querys que hagan lo mismo escritos en forma diferente, para el ejemplo podríamos
tener cuatro combinaciones básicas, usando IN y un subquery correlacionado, IN y un
subquery no-relacionado, también podemos usar EXISTS y un subquery correlacionado o
uno no-relacionado.

En esencia, un subquery correlacionado referencia la tabla externa mientras que uno no-
relacionado no referencia la tabla externa. Un subquery correlacionado es evaluado una
vez por fila procesada en el query padre, mientras que un subquery no-relacionado se
ejecuta una sóla vez y, el resultado es mantenido en memoria si es pequeño o en un
segmento temporal, si el resultado es grande. Un query no-relacionado que retorna un
solo valores llamada un subquery scalar. En este caso el optimizador sustituye el
resultado como una constante y ejecuta el subquery UNA sola vez.
Veamos un ejemplo de un mismo subquery escrito correlacionado y no-relacionado:

No-relacionado

select
count(*)
from
table1
where
key in
(select key from table2);

Correlacionado

Select
Count(*)
From
Table1
Where
Key in
(select key from table2 where table1.key = table2.key);

¿Cuál de estos dos será más eficiente?


Eso depende de la cantidad de filas retornadas por el query padre y por el subquery.
Debemos balancear la sobrecarga asociada con cada tipo de subquery:

Subquery correlacionado: es re-ejecutado una vez por cada fila retornada


en el query externo. Por lo tanto debemos asegurar que el subquery use un
índice siempre que sea posible.
Subquery no-relacionado: es ejecutado una vez, y el resultado es
normalmente ordenado y mantenido en un segmento temporal. Si el resultado
es muy grande tendremos problemas al ordenar y almacena el resultado en un
segmento temporal.

Como reglas generales podemos decir:

Cuando se utiliza un subquery correlacionado, los resultados son identicos


para la claúsula IN y EXISTS.
La claúsula EXISTS no es apropiada para querys no-relacionados.
Cuando un query padre retorna un número relativamente pequeño de filas,
un subquery correlacionado se ejecuta más rapido que un subquery no-
relacionado.
Cuando un subquery retorna un número pequeño de filas, un subquery no-
relacionado será más rapido que uno correlacionado.
Afinamiento de la utilización de memoria

El tamaño de memoria utilizado por Oracle es comunmente llamada la región Oracle. La


manera en que es manejada puede tener un gran impacto en el rendimiento y cada SGA
debe ser afinada de acuerdo a los requerimientos de la aplicación. Sin embargo debemos
recordar que la SGA recibe fuerzas dinámicas y una sola transacción puede ocasionar
problemas para otras. Cientos de transacciones pueden ser servidas concurrentemente,
cada una solicitando datos distintos. Afinar la memoria para cada actividad en un punto
en el tiempo puede no ser lo mejor en otro punto diferente.
Debido a la naturaleza dinámica de las bases de datos Oracle, sólo es posible una
afinamiento general.

Afinar la memoria utilizada por Oracle involucra un gran número de parametros y


carácterísticas:

Determinar el tamaño de la SGA


Afinar la PGA
Afinar el ordenamiento
Afinar el data buffer
Afinar el shared pool
Afinar el memory cache
Otros

Determinar el tamaño de la SGA


El archivo init.ora no sólo determina el tamaño global de la SGA sino también cuales
estructuras tendrá un tamaño específico de memoria. Oracle8 contiene 184 parametros
de inicialización.

Para ver el tamaño de la SGA, usted puede ejecutar el comando show SGA en el svrmgrl:

SVRMGRL>show sga

Total System Global Area 8252756 bytes


Fixed Size 48260 bytes
Variable Size 6533328 bytes
Database Buffers 1638400 bytes
Redo Buffers 32768 bytes

Afortunadamente, solo cinco parámetros son de importancia para el rendimiento global de


Oracle, aunque hay otros que también influyen:

db_block_buffers, este parámetro determina el número de database block buffers


que habrá en la SGA y representa el parámetro más importante para la memoria de
Oracle
db_block_size, el tamaño de los bloques de base de datos pueden provocar un gran
mejoramiento en el rendimiento. Mientras el valo por defecto es de 2048 bytes, las
bases de datos con tablas enormes y full-scan tables verán un gran mejoramiento
incrementando el db_block_size.
log_buffer, este parámetro determina la cantidad de memoria reservada para los
buffers de redo log. Si hay una gran actividad de actualización, al log_buffer debería
reservarsele más espacio.
shared_pool_size, este parámetro define el área que es compartida por todos los
usuarios en el sistema, incluye áreas para SQL y caché del diccionario de datos.
large_pool_size, este parámetro define un área de memoria es utilizado
exclusivamente para ordenar. Sólo es valido cuando se usa el multithreaded server,
pero tiene un gran impacto en el área de memoria compartida, ya que segrega la
memoria utilizada para ordenamiento del resto de áreas.

Afinando la PGA
Como se ha mencionado anteriormente, la SAGA no es la única memoria disponible para
los programas. La PGA es un área privada de memoria reservada para tareas externas.
Es utilizada para mantener información específica de la aplicación, tales como valores de
los cursores, reservar memoria para ordenamientos internos. Los siguientes dos
parámetros influencian el tamaño de la PGA:

open_links, define el máximo numeo de sesiones remotas concurrentes


que un proceso puede inciar. El valor por defecto es de cuatro, lo que significa
que una sentencia SQL puede referenciar hasta un máximo de cuatro bases de
datos dentro de un query.
sort_area_size, define la máxima cantidad de memoria PGA que puede
ser usada para ordenamientos en disco. Para sorts muy largos, Oracle
ordenará los datos en el tablespace temporal y el area definida en el
sort_area_sizee será utilizada para manejar este proceso. Cuando se utiliza el
multithreaded server, el area de sort es tomada de otra area definida por el
large_pool_size.

Afinando el Ordenamiento
A menudo olvidado a la hora de afinar, el ordenamiento en Oracle se realiza
implícitamente cuando ejecutamos un CREATE INDEX, ORDER BY o GROUP BY.

En el momento de que una sesion empieza, se reserva una pequeña ára en memoria para
ser utilizada en caso de ocurrir un ordenamiento. Desafortunadamente, la cantidad de
memoria debe ser la misma para todas las sesiones, no es posible agregar areas
adicionales para tareas que hagan mucho sort. No obstante, el DBA debe buscar un
balance que permita reservar suficiente área de sort para evitar ordenamientos en disco
para las tareas que lo requieran, aunque para la mayoría de los procesos talvez no se
utilize.

El tamaño del área privada es determinada por el parámetro sort_area_size. El tamaño


de cada sort individual es especificado por el sort_area_retainde_size. Siempre que un
sort no puede ser completado dentro del espacio asignado, se invocará un sort en disco,
el cual utiliza el tablespace temporal. Como regla general, sólo la creación de un índice o
el ORDER BY deberían hacer sort en disco.
Los ordenamientos en disco son costos por varias razones. Primero, consumen recursos
en el tablespace temporal. Oracle debe reservar bloques en el buffer para retener los
bloques en el tablespace temporal. Los sorts en memoria son siempre preferibles que los
sorts en disco ya que seguro retardarán esa tarea en particular e impactarán en algún
grado las otras tareas concurrentes en la instancia. También un excesivo ordenamiento
en disco, causará un alto valor de esperas por buffers libres, paginando los bloques de
otras tareas fuera del buffer.

Podemos ver la cantidad de sorts en memoria y en disco ejecutando el siguiente query:

Column value format 999,999,999


Select name, value from v$sysstat
Where name like 'sort%';

por ejemplo:

NAME VALUE
--------- ----------
sorts(memory) 7,019
sorts(disk) 49
sorts(rows) 3,288,608

Podemos ver que sólo 49 de 7068 sorts fueron realizados en disco, lo cual es cerca de un
1%, lo cual es probablemente aceptable para un sistema en particular.

Afinando el buffer de datos


Cuando se hace una petición de datos, Oracle primero busca en las estructuras internas
de memoria para ver si los datos ya están en el buffer. De esta manera Oracle evita
hacer I/O innecesario. Obviamente si el costo de la memoria fuera aún más económico,
podrías tener una base de datos con todos los datos cargados en memoria, pero esto no
es realizable en la vida real.

A lo mejor, podemos reservar una parte de memoria real para los buffers y Oracle se
encargará de administralos. Oracle utiliza el algoritmo LRU para determinar cuales
páginas de memoria deben ser liberadas.

En la mayoría de los sistemas UNIX los bloques de base de datos están definidos de 2K.
Recordemos que el I/O es el mayor retardo que existe un sistema cliente/servidor, y entre
más información relevante puede ser traida en cada I/O, mejor será el rendimiento. El
costo de leer un bloque de 8K no es significativamente mayor que leer 2K. Sin embargo,
la lectura de un bloque de 8K, no será de beneficio si sólo se necesita una pequeña fila,
ahora bien si las tablas son leídas en forma completamente a menudo, entonces podemos
tener enormes beneficios cambiandonos a bloques más grandes.

Para sistemas orientados a reportes, siempre es recomendable los bloques grandes. Sin
embargo, la mayoría de las bases de datos utilizadas para procesamiento en línea en la
noche realizan procesos tipo batch, por lo que casi siempre un tamaño de bloque de 8K
será de gran beneficio casi siempre.
Para determinar como se está comportando actualmente la base de datos podemos correr
el siguiente script, cuyo resultado DEBE ser siempre mayor a 70, sino se debe
incrementar el parámetro db_block_buffers.

Select trunc((1-(sum(decode(name, 'physical reads', value, 0))/


(sum(decode(name, 'db block gets', value,0))+
(sum(decode(name,'consistent gets', value,0)))))
) * 100) "Buffer Hit Ratio"
from V$SYSSTAT;

Esta estadística es recolectada desde el momento que arranca la base de datos, asi que
es posible que varíe de un día a otro dependiendo de la carga, siempre debe tratarse de
ejecutar en dias normales, no en cierres.

Una cosa que podemos hacer y que puede mejorar el rendimiento ostentiblemente es
parametrizar el __small_table_threshold, el cual define el tamaño de las tablas o índices
que puede ser localizadas en el espacio del buffer cache, normalmente no más del 10%
de la SGA.

Hoy día la mayoría de las bases de datos residen en un solo servidor. En este caso
podemos predicir cuanta memoria estará libre despues de calcular el consumo del Kernel
de UNIX (50MB) y de la PGA, la cual podemos calcular como el tamaño del
sort_area_size por la cantidad de usuarios en línea; por ejemplo si tenemos un equipo con
10 usuarios y 20MB de sort_area_size, entonces la PGA medirá 200MB.

Afinando el Shared Pool Size


El shared pool es utilizado primordialmente para almacenar cursores SQL compartidos,
procedimientos almacenados, e información de sesión, y funcionar como un caché para
para el diccionario y el library cache.

Library Cache
Las areas SQL compartidas y las áres PL/SQL son llamadas el library cache, es cual es
un subcomponente del shared pool. El promedio de fallos (cache miss ratio) le indica al
DBA si debe o no agregar más espacio al shared pool, en general si el cache miss ratio es
mayor a 1, deberiamos considerar agregar espacio al shared_pool_size.
El siguiente script nos indica el estado del library cache:

COLUMN "LIBRARY CACHE MISS RATIO" FORMAT 99.9999


COLUM "executions" FORMAT 999,9999,999
COLUMN "Cache misses while executing" FORMAT 999,999,999
Select
sum(pins) executions, sum(reloads) "Cache misses while executing",
(((sum(reloads)/sum(pins)))) "LIBRARY CACHE MISS RATIO"
from
V$LIBRARYCACHE;
por ejemplo puede resultar:

executions Cache misses while executing LIBRARY CACHE MISS RATIO


--------------- ----------------------------------------- -------------------------------------------
251,272 2,409 .0096

Cache del Diccionario


El cache del diccionario es utilizado para almacenar filas de las tablas internas de Oracle,
incluyendo el SQL de los paquetes. Un paquete la primera vez que se invoca va a
provocar un fallo de cache, pero los otros usuarios se van a beneficiar porque lo
encontrarán en memoria.

El resultado del siguiente script debe ser mayor a 90, de lo contrario el remedio es
incrementar el shared_pool_size:

COLUMN "Data Dict. Gets" FORMAT 999,999,999


COLUMN "Data DICT. cache misses" FORMAT 999,999,999
Select
Sum(gets) "Data Dict. Gets",
Sum(getmisses) "Data Dict. cache misses",
Trunc((1-sum(getmisses)/sum(gets)))*100) "DATA DICT CACHE HIT
RATIO"
From V$ROWCACHE;

por ejemplo:

Data Dict. Gets Data Dict. cache misses DATA DICT CACHE HIT RATIO
--------------------- --------------------------------- -------------------------------------------
409,288 11,639 97
¿Cómo determinar cuando reconstruir índices?

Uno de los problemas con muchas bases de datos Orale es su gran tamaño. Para
algunas muy grandes, realizar una reorganización de la Base de Datos es impráctica por
la cantidad de tiempo(días) que tomaria exportar los datos a cinta, borrar y recrear luego
la base de datos. Por esta razón debemos tratar mantener la base bien afinada sin
necesidad de una restructuración total.

En Oracle, bajo condiciones un índice casi nunca requeriría reconstruirse a menos que
exista gran cantidad de actividad de modificación y borrado contra las columnas
indexadas. El INSERT no causa problemas a los índices.

Ahora bien, ¿como determinar cuales índices se beneficiarían de una reconstrucción?.


Para hacer esto podemos ejecuta el siguiente comando:

Analyze index index_name validate structure;

el resultado sería mas o menos:

SQL>select * from index_stats;

HEIGTH 3
BLOCKS 5636
NAME INDEX_NAME
.....
DEL_LF_ROWS 41031
DEL_LF_ROWS_LEN 3956
DISTINCT_KEYS 7

Las siguientes son muy útiles para determinar si se debe reconstruir un índice:

Height, se refiere al máximo número de niveles encontrado dentro del


índice. Un índice deberia tener 90% de los nodos en tres niveles, pero cuando hay
mucha actualización y borrado pueden producirse más niveles. Siempre que el
valor de height sea mayor a 3, nos podríamos beneficiar de una una
reconstrucción del índice.
Del_lf_rows, se refiere al numero de hojas que han sido marcadas para
ser borradas del índice. Esto ocurre cuando existe alta activdad de update dentro
del índice e indica que el índice debe ser reconstruído.
distinct_keys, indica el número de llaves distintas dentro de un índice, a
este se le llama la cardinalidad del índice, y aquellos indices con valores menores
a 20 son candidatos para ser recreados como indices bitmap.
most_repeated_key, cuenta el valor que más se repite dentro de un índice
no único.
Utilización de UTLBSTAT y UTLESTAT

Como mencionamos anteriormente hay ciertas vistas que guardan estadísticas de la base
de datos, las cuales empiezan cuando se levanta la base de datos y se pierden cuando se
baja esta.

Oracle provee dos scripts localizados en $ORACLE_HOME/rdbms/admin, llamados


utlbstat.sql y utlestat.sql, los cuales nos permiten almacenar en tablas la información
estadística para su posterior revisión sin que se pierdan cuando se baja la base de datos.

El script utlbstat, arranca crea algunas tablas para recolectar las estadísiticas. Es
recomendable, modificar este script para que estas tablas sean creadas en un tablespace
aparte o modificar el usuario system para que el default tablespace sea otro distinto a
SYSTEM.

El utlestat, colecta información de las vistas dinámicas mantenidas por Oracle y la guarda
en tablas, además genera un archivo .txt con la información más importante.

SQL trace facility


Esta facilidad de Oracle nos permite determina punto por punto todos los recusos
consumidos por una aplicación en particular, sea una forma o un reporte.

Para poder utilizar esta facilidad debemos chequear los siguientes parámetros de la base
de datos:

TIMED_STATISTICS, este parámetro habilita o deshabilita la recolección de


estadísticas, tales como CPU y tiempos utilizados por la facilidad de SQL Trace así
como la recolección de ciertas estadísticas en las tablas dinámicas de rendimiento. El
valor por defecto es FALSE. Si deseamos utilizar el trace debe estar en TRUE.
MAX_DUMP_FILE_SIZE, es el tamaño del archivo en el sistema operativo definido
para los archivos de trace, por defecto su tamaño es de 500 bytes, lo cual es muy
pequeño.
USER_DUMP_DEST, especifica la ruta precisa donde se van a grabar los archivos de
trace. Este valor tambien puede ser modificado con: ALTER SYSTEM SET
USER_DUMP_DEST=newdir.

Luego de lo anterior debemos asegurar alguna manera de distinguir los trace files, como
puede haber muchos archivos, será bien difícil reconocer cual pertenece a la aplicación
que estamos queriendo hacerle trace. Para hacer esto podríamos poner en alguna parte
de la aplicación un select como: SELECT 'program name' from dual, de esta manera
luego con un utilitario como el grep podríamos buscar cual trace es el que nos interesa.

Existe otra manera un poco más primitiva que sería borrar antes de ejecutar nuestra
aplicación todos los traces existentes y luego será facil encontrar el trace que nos interesa
porque debería ser el primero o alguno de los primeros.
Para habilitar el SQL trace ejecutamos el siguiente comando:

ALTER SESSION SET SQL_TRACE = TRUE;

Y para desahabilitarlo:

ALTER SESSION SET SQL_TRACE = FALSE;

TKPROF
El tkprof acepta como entrada un archivo de trace y produce un archivo de salida
formateado, tambien puede ser utilizado para generar planes de ejecución.

Veamos un ejemplo del tkprof para el siguiente query:

SELECT * FROM emp, dept WHERE emp.deptno = dept.deptno;

call count cpu elapsed disk query current rows


---- ------- ------- --------- -------- -------- ------- ------
Parse 1 0.16 0.29 3 13 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 1 0.03 0.26 2 2 4 14

Misses in library cache during parse: 1


Parsing user id: (8) SCOTT

Rows Execution Plan


------- ---------------------------------------------------
14 MERGE JOIN
4 SORT JOIN
4 TABLE ACCESS (FULL) OF 'DEPT'
14 SORT JOIN
14 TABLE ACCESS (FULL) OF 'EMP'

La sintaxis del tkprof es:

Tkprof archivo1 archivo2 explain=user/password sort=xxxx

archivo1 es el archivo trace, archivo2 es el archivo de salida.


xxxx es igual a uno de los siguientes:

PRSCNT number of times parsed

PRSCPU CPU time spent parsing

PRSELA elapsed time spent parsing

PRSDSK number of physical reads from disk during parse

PRSMIS number of consistent mode block reads during parse


PRSCU number of current mode block reads during parse

PRSMIS number of library cache misses during parse

EXECNT number of executes

EXECPU CPU time spent executing

EXEELA elapsed time spent executing

EXEDSK number of physical reads from disk during execute

EXEQRY number of consistent mode block reads during execute

EXECU number of current mode block reads during execute

EXEROW number of rows processed during execute

EXEMIS number of library cache misses during execute

FCHCNT number of fetches

FCHCPU CPU time spent fetching

FCHELA elapsed time spent fetching

FCHDSK number of physical reads from disk during fetch

FCHQRY number of consistent mode block reads during fetch

FCHCU number of current mode block reads during fetch

FCHROW number of rows fetched


Interpretando la salida del tkprof
El tkprof lista las estadísticas de una sentencia SQL en filas y columnas. Cada fila
corresponde a uno de tres pasos en el procesamiento de una sentencia SQL:

Este paso traduce la sentencia SQL en el plan de ejecución. Este paso incluye
Parse
chequeos de autorización de seguridad, existencia de tablas, columnas y otros
objetos referenciados.
Este paso es la ejecución de la sentencia por Oracle. Para sentencias INSERT,
Execute
UPDATE, DELETE este paso realiza también la modificación de los datos; para
setencias SELECT este paso identifica las filas seleccionadas.
Fetch Este paso recupera las filas retornadas por la consulta. Este paso es sólo realizado
por sentencias SELECT.

Las otras columnas son estadísticas combinadas para todos los parses, todos los
executes y todos los fetches en la sentencia. Estos valores son 0 si el parámetro
TIMED_STATISTICS está en FALSE.

count
Número de veces que la sentencia fue parsed, executed o fetched.
cpu Tiempo total de CPU en segundos para todos las llamadas de parse, execute o fetch
para la sentencia.
elapsed Tiempo total transcurrido en segundos para todos las llamadas de parse, execute o
fetch para la sentencia
disk Número total de bloques de datos leídos físicamente desde los datafiles en disco
para todos las llamadas de parse, execute o fetch para la sentencia
query Número total de buffers recuperados en modo consistente para todos las llamadas de
parse, execute o fetch para la sentencia.
current Número total de buffers recuperados en el modo actual. Los buffers son recuperados
en el modo actual para sentencias INSERT, UPDATE o DELETE.

Existen opciones en el tkprof, para almacena estos valores para hacer comparaciones
entre diversas corridas en el tiempo.
Laboratorio, Tuning SQL

1. Ejecutar los siguientes comandos en sqlplus con usuario system/manager :

create tablespace prueba


datafile '/home/oracle/prueba01.dbf' size 100M;

create user prueba identified by prueba


default tablespace prueba
quota unlimited on prueba;

grant dba to prueba;

2. En Unix ejecutar:

Imp userid=prueba/prueba file=prueba.dmp touser=prueba fromuser=prueba

3. Ejecutar sqlplus con el usuario prueba.

4. Ejecutar el comando: set autotrace on

5. Ejecute los siguientes querys, para cada uno, observe el plan de ejecución, ¿es el
óptimo?, ¿podría mejorarse?, prueba otras alternativas....., incluso crear índices
adicionales....

select count(cod_persona) from personas;

select /*+ index(personas pk_personas) */ count(cod_persona)


from personas;

select saldo from cuenta_efectivo where cod_empresa = 5;

select saldo from cuenta_efectivo where num_cuenta = 10;

select saldo from cuenta_efectivo where num_cuenta=100


and cod_empresa = '1';

select saldo from cuenta_efectivo where num_cuenta=100


and cod_empresa=1;

select cod_persona, nombre from personas where


fec_nacimiento = to_date('130999','DDMMYY');

select count(*) from cliente where estado = 'A';


select /*+ index(personas x) */ count(cod_persona) from
personas; (observe que no da error a pesar que el indice x no
existe)

select * from cliente where (cod_cliente = 10 or 10=10)


and (cod_oficial = 40000 or 40000=40000); (produce un full
scan)

select estado from cliente where (cod_cliente = '10' and


10 is not null); (es parte del query anterior pero
reformulado para no usar or, y se puede completar con UNION)

select count(*) from cliente where estado='A'; (note que


utiliza indice para recuperar pocas filas)

select count(*) from cliente where estado='V'; (note que


utiliza el índice a pesar de que recupera casi todos los
datos)

select count(*) from cliente where estado||'' = 'V';


(matamos el índice para que haga un full scan.

select count(*) from personas where cod_persona in


(select cod_cliente from cuenta_efectivo); (query no
relacionado)

select count(*) from personas, cuenta_efectivo where


cod_persona=cod_cliente;

select count(*) from personas, cuenta_efectivo where


cod_persona=cod_cliente(+);

select sum(saldo)
from cuenta_efectivo x
where cod_cliente in (select y.cod_cliente
from cliente y
where y.cod_oficial='39999'
and y.cod_cliente = x.cod_cliente);
(subquery correlacionado)

select sum(saldo) from cuenta_efectivo x, cliente y where


x.cod_cliente=y.cod_cliente and y.cod_oficial='39999'; (con
join)
Si desea conocer cuánto tiempo en realidad tarda un query
realizando puede hacer un script como el siguiente, en unix,
ejecute vi tiempos.sql y digite:

set serveroutput on
declare
x date;
y date;
z number;
begin
x:=sysdate;
select sum(saldo) into z from cuenta_efectivo;

y:=sysdate;
dbms_output.put_line(to_char(y-
x,'9.9999999999999999999999999999999'));
end;
/

sálvelo y en sqlplus ejecutelo asi: @tiempos.sql

el script le mostrará la diferencia en fracciones de día de la


duración del query.

Debemos tomar en cuenta que cuando ejecutamos un query, los datos


que este traiga, serán almacenados temporalmente en el buffer
cache, por esta razón la segunda vez que ejecutamos un mismo
query, el tiempo de ejecución va a ser mucho menor, si deseamos
repetirlo en las mismas condiciones deberiamos ejecutar lo
siguiente bajo el usuario system:

Alter system flush shared_pool;


Laboratorio, Tkprof y otros scripts

1. Entre al unix con el usuario Oracle.


2. Ejecute el svrmgrl, connectese con internal y levante la base de datos.
3. Ejecute el siguiente script para determinar la ruta donde quedan almacenados los
archivos de trace:

Select name, value


From sys.v_$parameter
Where name like '%user_dump_dest%';
4. En unix vaya a ese directorio y borre los archivos *.trc que existan.
5. Conéctese en sqlplus con el usuario prueba.
6. Ejecute en plus el siguiente comando

Alter session set sql_trace = true;

7. Ejecute el siguiente script:

select cod_persona, nombre, sum(SAL_TOTAL_CTA)


from personas p, cuenta_efectivo c
where p.cod_persona = c.cod_cliente
group by cod_persona,nombre;

8. Ejecute luego el comando:

Alter session set sql_trace = false;

9. En unix ejecute:

Tkprof xxx.trc salida.txt explain=prueba/prueba sort=PRSCPU

10. Observe con detenimiento el archivo salida.txt.


11. Repita el proceso de nuevo, observe la diferencia en los resultados. ¿qué sucedió?
Explique la razón de esto.
12. Entre al svrmgrl y ejecute:

SVRMGRL>show SGA

Observe los valores mostrados y trate de determinar de donde se calculan estos valores,
observando los parámetros que estén en el archivo iniXXXX.ora. Parámetros:
shared_pool_size, db_block_buffers, log_buffer

13. Ejecute el siguiente script:

Column value format 999,999,999


Select name, value from v$sysstat
Where name like 'sort%';

14. Ejecute este otro script y observe el resultado:

Select trunc((1-(sum(decode(name, 'physical reads',value,0))/


(sum(decode(name,'db block gets',value,0))+
(sum(decode(name,'consistent gets',value,0)))))
)*100) "Buffer Hit Ratio"
from v$sysstat;

15. Ejecute este script:

COLUMN "LIBRARY CACHE MISS RATIO" FORMAT 99.9999


COLUM "executions" FORMAT 999,9999,999
COLUMN "Cache misses while executing" FORMAT 999,999,999
Select
sum(pins) executions, sum(reloads) "Cache misses while executing",
(((sum(reloads)/sum(pins)))) "LIBRARY CACHE MISS RATIO"
from
V$LIBRARYCACHE;

16. Y, por último este otro script:

COLUMN "Data Dict. Gets" FORMAT 999,999,999


COLUMN "Data DICT. cache misses" FORMAT 999,999,999
Select
Sum(gets) "Data Dict. Gets",
Sum(getmisses) "Data Dict. cache misses",
Trunc((1-sum(getmisses)/sum(gets)))*100) "DATA DICT CACHE HIT
RATIO"
From V$ROWCACHE;
Seguridad y auditoría

La seguridad y los procedimientos establecidos nos ayudan a proteger el activo de mayor


crecimiento en las empresas: los datos. Y mientras que almacenar datos en la base de
datos y hacerlos disponibles para todos los usuarios, también nos conlleva a tener la
susceptibilidad de accesos no autorizados. Estos accesos deben ser prevenidos y
detectados.

Oracle tiene varios niveles de seguridad, y la habilidad de auditar cada nivel.

Capacidades de seguridad

Seguridad de cuenta
Para accesar los datos en cualquier base de datos Oracle, debemos tener acceso a una
cuenta. Este acceso puede ser directo (a traves de conecciones a la base de datos) o
indirecto. Las conexiones indirectas incluyen acceso a través de las ligas de base de
datos a bases localizadas remotamente. Además una cuenta puede ser "amarrada" a una
cuenta de usuario en el sistema operativo.

Cuando se crea una cuenta se le asigna un password. Este puede ser modificado por el
DBA o por el usuario. La base de datos almacena los passwords en forma encriptada en
una tabla del diccionario. Si la cuenta está amarrada al sistema operativo, el chequeo de
password no se realiza, esa función se le delega al sistema operativo.

A partir de Oracle8, los password pueden expirar, y el DBA puede establecer las
condiciones bajo las cuales un password en particular puede ser reutilizado. Además,
podemos usar profiles para reforzar estándares para los password (tales como longitud
mínima) y automáticamente podemos bloquear cuentas si ocurren multiples fallos para
conectarse.

Privilegios de Objetos
El acceso a los objetos dentro de la base de datos es realizado vía privilegios. Esto se
realia via el comando grant. Por ejemplo si el usuario RH es dueño de la tabla emp y
ejecuta el siguiente comando:

grant select on emp to public;

entonces todos los usuarios, tendrán la capacidad de seleccionar registros de la tabla


emp de RH. Los roles (grupos de privilegios), pueden ser utilizados para simplificar la
administración de los privilegios. Para aplicaciones con gran cantidad de usuarios, los
roles reducen grandemente el número de grants necesarios. Además los roles puede ser
protejidos via password y pueden ser habilitados o deshabilitados dinámicamente.
Roles y privilegios a nivel de Sistema
Podemos utilizar roles para administrar los comandos de sistema disponibles a los
usuarios. Estos comandos incluyen por ejemplo el create table o create index. Las
acciones contra cada tipo de objeto de la base de datos es autorizado a través de
privilegios separados. Por ejemplo, a un usuario se le puede dar el grant CREATE
TABLE, pero no el CREATE TYPE. Podemos crear roles personalizados tan detallados
como queramos y dandole a los usuarios sólo lo que requieren.

Implementando la seguridad

Seguridad del Sistema Operativo


No podemos accesar una base de datos a menos que primero podamos directa o
indirectamente accesar el servirdor en que la base de datos está coriendo. El primer paso
para asegurar la base de datos es asegurar la plataforma y la red en la cual reside la base
de datos. Una vez que esto es realizado, podremos considerar la seguridad del sistema
operativo.

Oracle utiliza una serie de archivos a los cuales los usuarios NO requieren acceso directo.
Por ejemplo los datafiles y los online redo log son escritos y leídos por los procesos
background de Oracle. Por lo tanto, sólo un DBA requiere acceso directo a estos archivos
al nivel de sistema operativo. Los vaciados de export y otros archivos de respaldo
también deben ser asegurados.

Creando usuarios
Cuando se crea un usuario, el objetivo es establecer una cuenta segura y útil que tenga
los privilegios adecuados y los seteos por defecto correctos. Cuando creamos un usuario
no tiene aún privilegios para conectarse, los cuales debemos otorga luego via grant.
Los posible parámetros a tomar en consideración a la hora de crear un usuario son:

Parámetro Uso
Username Nombre del esquema
Password Password para lacuena, puede estar asociada a la cuenta
del usuario en el sistema operativo
Default tablespace El tablespace por defecto en el cual serán creados los
objetos del usuario. Esta opción NO le da privilegios para
crear objetos, es sólo un valor por defecto.
Temporary tablespace El tablespace en el cual se utilizarán los segmentos
temporales durante transacciones de sort.
Quota Le permite al usuario almacenar objetos en el tablespace
especificado hasta un total máximo indicado por quota.
Profile Asigna un profile al usuario. Si no se asigna ninguno, se
utilizará el profile estándar. Los profiles se utilizan para
restringir recursos del sistema y para reforzar la
administración de las reglas aplicadas sobre los passwords.
Borrando usuarios
Un usuario puede ser borrado completamente de la base de datos con el comando DROP
USER. Este comando tiene el parámetro CASCADE, el cual a su vez borra todos los
objetos del usuario antes de borrar el usuario. Por ejemplo:

drop user RH cascade;

Cualquier vista, sinónimo, procedimiento, función o paquete que referencien objetos


pertenecientes a este usuario serán marcados como inválidos.

Privilegios a nivel de sistema


Podemos utilizar roles a nivel de sistema para habilitar comandos de sistema utilizados
para administrar la base de datos. Se pueden utilizar varios roles pre-configurados o
crear roles propios según las necesidades.

Cuando damos un role con grant, tenemos la opción "with grant option", la cual significa
que ese usuario puede a su vez otorgar ese rol a otros usuarios. Tambien algunos de los
roles tiene la opcion ANY, la cual significa que ese role pude crear objetos en el esquema
de otros usuarios.

A continuación veamos una tabla con algunos de los privilegios:

Privilegio Capacidades otorgadas

CREATE [ANY] INDEX Crear índices


CREATE [ANY] PROCEDURE Crear procedimientos, funciones o paquetes
CREATE [ANY] SEQUENCE Crear secuencias
CREATE [PUBLIC] SYNONYM Crear sinonimos privados o públicos
CREATE [ANY] TABLE Crear tablas, el usario debe tener una quota para el
tablespace o haber recibido UNLIMITED TABLESPACE
CREATE [ANY] TRIGGER Crear Triggers
CREATE [ANY] VIEW Crear vistas
ALTER ANY INDEX Alterar cualquier índice
ALTER ANY PROCEDURE Alterar cualquier procedimiento, funcion o paquete
ALTER ANY TABLE Alterar cualquier table. Además le da la capacidad de
compilar vistas en cualquier esquema.
DROP ANY INDEX Borrar cualquier índice
DROP ANY PROCEDURE Borrar cualquier procedemiento, función o paquete
DROP ANY SEQUENCE Borrar cualquier secuencia

ALTER SESSION Alterar parámetros de la sesión


CREATE SESSION Conectarse a la base de datos
CREATE [PUBLIC] DATABASE Crear ligas a otras bases de a
LINK
CREATE PROFILE Crear profiles para los usuarios
CREATE ROLE Crear roles
CREATE TABLESPACE Crear tablespaces
CREATE USER Crear nuevos usuarios

Existen ocho roles a nivel de sistema que vienen configurados con la base de datos, estos
son: CONNECT, RESOURCE, DBA, IMP_FULL_DATABASE, EXP_FULL_DATABASE,
SELECT_CATALOG_ROLE, EXECUTE_CATALOG_ROLE y
DELETE_CATALOG_ROLE.

El role connect, es el que típicamente se le otorga a los usuarios. Aunque este role tiene
algunas capacidades limitadas de creación de objetos, no le otorga ninguna quota al
usuario, por lo tanto si no le damos una quota no podrá crear objetos. En general es
mejor otorgar a los usuarios normales sólo el privilegio CREATE_SESSION.

El role resource se le otorga a los desarrolladores, éste tiene la mayoría de los permisos
requeridos normalmente por un desarrollador.

El role dba incluye TODOS los privilegios a nivel de sistema. En general no debería haber
más de un usuario con role dba por base de datos.

Los roles IMP_FULL_DATABASE y EXP_FULL_DATABASE son utilizados durante


operaciones de import y export.

En un ambiente organizaciónal muy grande podriamos delegar la función de crear


usuarios fuera del DBA para facilidad de administración, sin otorgar más que lo necesario
para realizar esta funcion. Por ejemplo:

create role account_creator;

grant create_session, create user, alter user


to account_creator;

luego este nuevo rol se lo damos por ejemplo a alguna persona del departamento de
Recursos Humanos.

También por razones de seguridad, podríamos asignarle los roles necesarios a un usuario
pero luego ejecutar el siguiente comando:

alter user RH default role NONE;

y luego programáticamente en las aplicaciones habilitamos o deshabilitamos los roles


según se necesiten:

alter user RH default role account_creator;


de esta manera si el usuario se conecta a la base de datos con una herramienta distinta
como SQL*Plus, éste no tendría ningún role habilitado al momento de conectarse y por lo
tanto no podría hacer mayor cosa en la base de datos.

Profiles de Usuario
Podemos utilizar profiles para configurar límites a la cantidad de recursos del sistema y de
la base de datos disponibles para el usuario, si no se especifica ninguno, se utiliza el
default que asigna recursos ilimitados para los usuarios.

Veamos que valores podemos definir en un profile:

Recurso Descripción

SESSION_PER_USER El número de sesiones concurrentes que un


usuario puede tener en una instancia
CPU_PER_SESSION El tiempo de CPU, en centésimos de segundo que
puede utilizar una sesión
CONNECT_TIME El número de minutos que una sesión puede estar
conectada a la base de datos
IDLE_TIME El número de minutos que una sesión puede estar
conectada sin ser utilizada.
LOGICAL_READS_PER_SESSION Número de bloques de base de datos que pueden
ser leídos en una sesión.
FAILED_LOGIN_ATTEMPTS El número de intentos consecutivos de fallos de
conexión que causarán que se bloquee una
cuenta.
PASSWORD_LIFE_TIME El número de días que puede ser utilizado un
password
PASSWORD_REUSE_TIME El numero de dias que deben pasar antes de que
pueda ser reutilizado un password
PASSWORD_REUSE_MAX El número de veces que debe ser cambiado el
password antes de que pueda reutilizarse el
mismo.
PASSWORD_LOCK_TIME El número de días que una cuenta será bloqueada
si el FAILED_LOGIN_ATTEMPTS es excedido.
PASSWORD_GRACE_TIME Número de días de gracia que transcurren luego
de ser excedido el PASSWORD_LIFE_TIME
PASSWORD_VERIFY_FUNCTION El nombre de la fncion utilizada para evaluar la
complejidad del password, Oracle provee una que
podemos modificar.

Los profiles son creados con el comando "create profile" y modificados con el comando
"alter profile".
Asociando las cuentas de base de datos a cuentas del Sistema Operativo
Para facilitar la administración de usuarios, si tenemos un sistema operativo confiable (NO
WINDOWS), podemos definir las cuentas de usuarios de modo que el password y la
cuenta sean las mismas del sistema operativo.

En la base de datos estas cuentas tendrán por defecto el prefijo "OPS$" mas el userid.
Por ejemplo consideremos una cuenta de usuario llamado JDURAN. En la base de datos
el usuario será OPS$JDURAN, luego de que este usuario accese el sistema operativo,
podrá conectarse a Oracle sin poner ni usuario ni password:

>sqlplus /

para crear un usuario en estas condiciones debemos utilizar "identified externally" en el


create user:

create user OPS$JDURAN


identified externally
default tablespace USERS
temporary tablespace TEMP;

Cuando se utiliza la claúsula "identified externally", esto fuerza a la base de datos a


validar la cuenta contra el sistema operativo.

Privilegios a nivel de Objetos


Los privilegios a nivel de objetos le dan a los usuarios acceso a los datos de los cuales
ellos no son dueños. Podemos utilizar roles para facilitar la administración de privilegios.

Los privilegios son otorgados con el comando grant y son almacenados en el diccionario
de datos. A los usuarios les podemos dar permiso para accear tablas, vistas, secuencias
más la habilidad para ejecutar procedimientos, funciones y paquetes.

Los posibles privilegios de objetos son:

Privilegio Capacidades otorgadas

SELECT Poder consultar un objeto


INSERT Poder insertar filas en un objeto.
UPDATE Poder actualizar filas de un objeto. Este
priviliegio puede ser otorgado sobre
columnas específicas
DELETE Poder borrar filas de un objeto
ALTER Poder alterar un objeto
INDEX Poder crear índices sobre una table
REFERENCES Poder crear llaves foráneas que referencien
una tabla
EXECUTE Poder ejecutar funciones, paquetes o
funciones
READ Poder accesar un directorio
Debemos tomar en cuenta que también podemos revocar privilegios o roles de un usuario
utilizando:

revoke delete on emp from RH;

además si un usuario tiene el privilegio select sobre una tabla pero vía rol y desea crear
una vista que utiliza esta tabla, NO podrá crear esa vista a menos que le demos un grant
directo sobre la tabla a ese usuario.

A menudo requerimos revisar que privilegios tiene otorgados un usuario o rol particular,
para esto tenemos una serie de vistas:

Vista del Diccionario Contenido

DBA_ROLES Nombres de los roles


DBA_ROLE_PRIVS Usuarios a los que les ha sido otorgado
roles
DBA_SYS_PRIVS Usuarios a los que se les ha otorgado
privilegios del sistema
DBA_TAB_PRIVS Usuarios a los cuales se les ha otorgado
privilegios sobre tablas
DBA_COL_PRIVS Usuarios a los cuales se les ha otorgado
privilegios sobre columnas específicas de
tablas
ROLE_ROLE_PRIVS Roles que han sido otorgados a otros roles
ROLE_SYS_PRIVS Roles a los que se les ha otorgado
privilegios del sistema
ROLE_TAB_PRIVS Roles a los que se les ha otorgado
privilegios sobre tablas

Por ejemplo para saber qué privilegios del sistema han sido otorgados a cuáles roles,
podemos ejecutar el siguiente script:

Select
Role,
Privilege,
Admin_option
From role_sys_privs;

O para determinar qué grants se le ha otorgado a los usuarios sobre qué tablas:

Select
Grantee,
Owner,
Table_name,
Grantor,
Privilege,
Grantable
From dba_tab_privs;
Adicionalmente hay dos vistas, que listan los privilegios y roles habilitados actualmente
para una sesión:

SESSION_PRIVS, lista todos los privilegios del sistema disponibles para la


sesión, ya sean grants directos o vía rol.
Lista todos los roles habiltados para la sesión.

Limitando los comandos disponibles, Product User Profiles


Dentro de SQL*Plus, se ofrece un nivel adicional de seguridad, permitiendo habilitar o
deshabilitar comandos específicos. De esta manera, los usuarios con el privilegio de
UPDATE en una tabla pueden ser prevenidos de utilizar SQL*Plus para actualizar la tabla
de manera NO controlada.

Esta capacidad le permite a los DBA, evitar que los usuarios accesen el sistema operativo
desde SQL*Plus vía el comando "host". También se puede deshabilitar el comando
"connect", lo cual los obliga a permanecer sólo en su cuenta propia.

SQL>host
invalid command: host
SQL>connect system/manager
invalid command: connect

Para habilitar este nivel de seguridad, debemos crear las tablas del Product User Profile.
El script para crearlas se encuentra en $ORACLE_HOME/sqlplus/admin y se llama
pupbld.sql. Este script crea varias tablas y vistas y debe ser ejecutado dentro de la
cuenta SYSTEM.

En la siguiente tabla se muestran las columnas importantes para esta carácterística:

Nombre de la columna Descripción

PRODUCT Poner "SQL*Plus", tal y como está escrito.


USERID El nombre del usuario en mayúsculas, o
xxx% para varios usuarios o % para todos
los usuarios
ATTRIBUTE El nombre en mayúsculas del comando a
ser deshabilitado.
CHAR_VALUE Poner en "DISABLED" en mayúsculas.
Auditando
La base de datos tiene la capacidad de auditar todas las acciones que ocurren dentro de
ella. Estos registros son escritos a una tabla (SYS.AUD$) o al sistema operativo. La
haiblidad de utilizar el sistema operativo depende de cuál se utilize.

Se pueden auditar tres distintos tipos de acciones: intentos de conexión, acceso a objetos
y acciones de base de datos.

Para habilitar la auditoría, el archivo init.ora debe tener configurado el parámetro


AUDIT_TRAIL con cualquiera de estos valores:

NONE, auditoría deshabilitada


DB, habilita la auditoría escribiendo a la tabla sys.aud$
OS, habilita la auditoría utilizando la característica de auditoría que ofrezca
el sistema operativo.

Existen varias vistas para ver en forma legible los datos almacenados en sys.aud$,
DBA_AUDIT_SESSION es una de ellas, por ejemplo para ver los intentos exitos o fallidos
de conexión podemos ejecutar el siguiente comando:

Select
os_username,
username,
terminal,
decode(returncode, '0','Connected',
'1005', 'FailedNull',
'1017', 'Failed', Returncode),
to_char(timestamp, 'DD-MON-YY HH24:MI:SS'),
to_char(Logoff_time, 'DD-MON-YY HH24:MI:SS')
from dba_audit_session;

Además podemos auditar eventos u objetos especiales con el comando:

audit xxxx;

donde xxxx puede ser, DATABASE LINK, INDEX, PROFILE, ROLE, SESSION, TABLE,
TRIGGER, TABLESPACE, etc... , o sea cada vez que se cree, borre o modifique alguno
de estos, se dejará una huella en la auditoría de la base de datos.
Para ver la auditoría de estas acciones podemos ejecutar el siguiente script:

Select
Os_username,
Username,
Terminal,
Owner,
Obj_name,
Action_name,
Decode(returncode,'0','Success',returncode),
To_char(timestamp,'DD-MON-YY HH24:MI:SS')
From dba_audit_object;

Tambien podemos auditar acciones específicas sobre un objeto u objetos:

Audit insert on RH.emp;


Audit all on RH.emp;
Audit delete on RH.emp;

los registros resultantes de este auditoraje quedan en la vista DBA_AUDIT_OBJECT, con


esto podemos determinar con exactitud quién hizo qué cosas sobre qué tablas y en que
momento específico. Lo único que debemos tener en cuenta es que estas tablas de
auditoría crecerán mucho, provocando problemas en el tablespace SYSTEM, y debemos
limpiar regularmente esta auditoría para liberar espacio .
Respaldo y Recuperación

Existen tres posibles métodos para respaldar una base de datos Oracle: exports, offiline
backups y online backups (ARCHIVELOG).

Respaldos Lógicos
Un respaldo lógico de la base de datos involucra leer un conjunto de registros y escribirlos
a un archivo. Estos registros son leídos independientemente de su ubicación física. En
Oracle, el utilitario export es utilizado para realizar este tipo de respaldos.

Export
El utilitario export lee la base de datos, incluyendo el diccionario de datos, y escribe la
salida a un archivo binario llamado archivo de vaciado de export. Podemos exportar
TODA la base de datos (full), usuarios específicos o tablas específicas. Durante los
exports, se puede escoger si queremos exportar información asociada a las tablas como
grants, índices y constraints. El archivo escrito por el export, contiene todos los
comandos necesarios para completar la recreación de todos los objetos escojidos.

Un full export puede ser realizado para todas las tablas (llamado tambien export
Completo), o sólo para algunas tablas que hayan cambiado desde el último export.
Existen dos tipos diferentes de export incremental: Incremental y Acumulativo. El
incremental exporta todas las tablas que han cambiado desde el último export, mientras
que el acumulativo exporta todas las tablas que han cambiado desde el último full export.

Import
Una vez que los datos son exportados, puede ser importados utilizando el utilitario import.
Este lee el archivo binario generado por el export y ejecuta los comandos que encuentre
dentro de este. Por ejemplo estos comandos podrían ser create table seguido de un
insert para cargar los datos.

Los datos que fueron exportados no tienen necesariamente que ser importados dentro de
la misma base de datos o el mismo esquema donde se realizó el export.

Podemos importar todo o parte de los datos. Si importamos un Full export en forma total,
entonces todos los objetos de la base de datos, incluyendo tablespaces, datafiles y
usuarios serán creados durante el import. Sin embargo, a menudo es útil pre-crear los
tablespaces y los usuarios de modo que podamos cambia la distibución física de los
objetos dentro de la base de datos.
Respaldos físicos
Los respaldos físicos involucran copiar los archivos que constituyen la base de datos sin
importar su contenido lógico. Estos respaldos también se les conoce como respaldos a
nivel de sistema de archivos porque conllevan utilizar utilitarios del sistema operativo para
realizarlo.

Offline Backups
Los offline backups ocurren cuando la base de datos ha sido bajada normalmente (o sea,
no por una falla de la instancia). Mientras la base de datos está "offline", se respaldan los
siguientes tipos de archivos:

Todos los datafiles


Todos los control files
Todos los online redo logs
El archivo init.ora

Es muy fácil respaldar estos achivos si utilizamos algún estándar en la estructura de


directorios.

Tener todos estos archivos respaldados mientras la base de datos está cerrada, nos
provee una imagen COMPLETA de la base de datos tal y como existía en el momento de
ser cerrada. Todos estos pueden ser restaurados posteriormene y la base de datos
funcionará normalmente.

Online (ARCHIVELOG) backups


Podemos utilizar los online backups para cualquier base de datos que esté corriendo en
modo ARCHIVELOG. En este modo, los online redo logs son archivados, creando una
bitácora completa de todas las transacciones dentro de la base de datos.

Se puede realizar un respaldo a nivel de sistema de archivos mientras la base de datos


está abierta si esta configurada con el ARCHIVELOG. Un respaldo en línea involucra
setear cada tablespace en un estado de respaldo, luego respaldar sus datafiles y, luego
restaurar su estado a modo normal. La base de datos puede ser completamente
recuperada vía los archived redo logs.

En un respaldo en línea se respaldan estos archivos:

Todos los datafiles


Todos los redo logs archivados
Un control file, via el comando alter database

Los respaldos en línea son muy poderosos. Primero, nos proveen una recuperación
completa a un punto en el tiempo y, segundo permiten que la base de datos permanezca
abierta durante el respaldo. Sobre todo es importante en empresas donde las bases de
datos no pueden ser bajadas porque se utilizan las 24 horas. Además hay un beneficio
adicional, al permanecer abierta, la SGA no se pierde, por lo tanto los caches permanecen
intactos.
Implementación

Export
El utilitario export tiene tres niveles de funcionalidad: full, user, table.
En el modo full, se exporta TODA la base de datos. Todo el diccionario de datos es leído
y se escriben los DDL necesarios para recrear completamente la base de datos. Este
archivo incluye definiciones para todos los tablespaces, todos los usuarios, y todos los
objetos, datos y privilegios.

En el modo user, se exportan los objetos de un usuario junto con su definición y datos.
Todos los grants e índices creados por el usuario sobre los objetos del usuario son
exportados. Grants e índices creados por otros usuarios NO son exportados en esta
opción.

En el modo table, se exportan una o más tablas específicas. La estructura de la tabla, los
datos y los grants son exportados.

Veamos los posibles parámetros del export y su funcionalidad:

Parámetro Descripción

USERID Usuario y password que está ejecutando el export


BUFFER Tamaño del buffer utilizado para recuperar las filas.
FILE Nombre del archivo que va a generar el export
COMPRESS Es una bandera de valores Y o N que indica si el export
comprime o no todos los extents de una tabla en un solo
extent. Esto afecta la claúsula storage de los objetos
exportados.
GRANTS Es una bandara Y o N que indica si los grants sobre los
objetos exportados también serán exportados.
INDEXES Una bandera Y o N que indica si se exportan las definiciones
de los índices.
ROWS Una bandera Y o N que indica si se exportarán los datos, si
se indica N, entonces sólo se exportarán las definiciones
DDL de las tablas.
CONSTRAINTS Una bandera Y o N que indica si los constraints sobre las
tablas serán o no exportados.
FULL Si se pone Y, se realizará un full export.
OWNER Es una lista de los usuarios a ser exportados.
TABLES Lista de tablas a ser exportadas
RECORDLENGTH Longitud en bytes de los registros del archivo export,
normalmente se deja el default a menos que requiramos
pasar un export de un sistema operativo a otro distinto.
INCTYPE Indica el tipo de export a ser realizado, los valores válidos
son : COMPLETE, CUMULATIVE, INCREMENTAL
DIRECT Es una bandera Y o N que indica si se realiza la opción
directa. Esta opción se brinca el buffer cache durante el
export, generando ganancias significativas de rendimiento
durante el export
LOG El nombre de un archivo donde quedan todos los mensajes
o errores dados por el export
PARFILE El nombre de un archivo de texto conteniendo todos estos
parámetros

Opciones, Incremental vs Cumulative

Opción Descripción
COMPLETE Es el valor por defecto. Todas las tablas
especificadas serán exportadas.
CUMULATIVE Si se indica FULL=Y, entonces puede
utilizarse esta opción. Sólo aquellas tablas
que contengan filaes que hayan cambiado
desde el último Full export de cualquier tipo
serán exportadas
INCREMENTAL Si se indica FULL=Y, entonces puede
utilizarse esta opción. Exporta todas las
tablas cuyas filas hayan cambiado desde el
último export Cumulative o Complete.

Import
El utilitario impor lee los datos del archivo generado por el export y ejecuta los comandos
almacenados en él. Puede ser utilizado para restaurar selectivamente objetos o usuarios.

A continuación veamos los parámetros del import:

Parámetro Descipción
USERID Usuario y password de la cuenta que ejecuta el import.
BUFFER Tamaño del buffer utilizado para leer datos.
FILE Nombre del archivo generado por el export
SHOW Una bandera que muestra el contenido en vez de ejecutarlo
IGNORE Es una bandera que indica si el import debe ignorar los
errorres provocados por el create cuando algún objeto ya
exista.
GRANTS Es una bandera que indica si los grants serán importados o
no.
INDEXES Una bandera que indica si se importarán o no los índices.
ROWS Es una bandera que indica si se importarán los datos. Si se
especifica N, sólo se ejecutarán los comandos DDL de
creación de los objetos.
FULL Si se especifica Y, se importará el archivo completo
FROMUSER Una lista de usuarios cuyos objetos serán importados.
(Cuando FULL=N)
TOUSER Lista de usuarios sobre los cuales serán restaurados los
objetos
TABLES Lista de tablas a ser restauradas
RECORDLENGTH Longitud en bytes de los registros del archivo export,
normalmente se deja el default a menos que requiramos
pasar un export de un sistema operativo a otro distinto.
INCTYPE Indica el tipo de import a ser realizado, los valores válidos
son : COMPLETE, CUMULATIVE, INCREMENTAL
COMMIT Indica si el import debe hacer commit despues de cada
arreglo (tamaño del BUFFER), si se indice N, el import hará
commit después de cada tabla. Normalmente use Y, para
evitar problemas en los Rollback Segments durante el
import.
PARFILE El nombre de un archivo de texto conteniendo todos estos
parámetros
INDEXFILE Esta opción escribe todos los comandos: create table, create
cluster y create index a un archivo en luegar de ejecutar el
import. Este archivo puede ser utilizado y es muy útil para
separar las tablas de los índices.
LOG El nombre de un archivo donde quedan todos los mensajes
o errores dados por el export
ANALYZE Es una bandera que le indica al import si debe ejecutar los
comandos analyze encontrados en el archivo export.

Una opción muy utilizada es el Fromuser/Touser para mover datos entre usuarios, por
ejemplo podríamos ejecutar el siguiente comando:

imp system/manager file=rh.dmp fromuser=rh touser=rh_new rows=y indexes=y;


Offline backups
En un respaldo en frío, se respaldan TODOS los archivos que constituyen la base de
datos como hemos vistos previamente.

Si nuestra base de datos está ubicada en un subdirectorio /discox/oracle/DEMO, donde


discox puede ser disco1, disco2, etc.; en unix por ejemplo podríamos ejecutar el siguiente
comando para respaldar todos los archivos de la instanacia DEMO:

Tar -cvf /dev/rmt/ohc /disco[1-9]/oracle/DEMO

la opción -cvf se utiliza para crear un archivo nuevo de tar. Para agregarle a este archivo
el init.ora, que muy probablemente esté en otra localización podemos ejecutar:

tar -rvf /dev/rmt/ohc /orasw/app/oracle/DEMO/pfile/initDEMO.ora

Estos dos comandos, ejecutados en conjunto, respaldarán todos los archivos de la base
de dataos en un archivo en cinta.

Antes de ejecutar los comandos anteriores debemos entrar al svrmgrl y hacer un


shutdown de la base de datos.

Online backups (ARCHIVELOG)


Con este tipo de respaldos podemos realizar un respaldo de los archivos a nivel físico sin
tener que hacer shutdown de la base de datos.

En primer lugar debemos asegurarnos que la base de datos esté corriendo en


ARCHIVELOG, para esto podemos ejecutar lo siguiente en el svrmgrl:

svrmgrl
SVRMGR>connect internal
SVRMGR>startup mount DEMO;
SVRMGR>alter database archivelog;
SVRMGR>archive log start;
SVRMGR>alter database open;

También podemos configurar este modo en el init.ora para que siempre la base de datos
levante en el modo ARCHIVELOG, agregando estas dos lineas:

log_archive_dest = /disco1/oracle/arch/DEMO/arch
log_archive_start =TRUE

en el diretorio definido quedarán los redo logs archivados con una numeración
consecutiva. Nunca borre alguno de estos, no hay forma de recuperar una base de datos
si se pierde alguno.
En forma genérica podemos definir que para hacer un respaldo en caliente debemos:

1. Para cada tablespace que exista:


Poner el tablespace en modo backup.
Respaldar los datafiles del tablespace
Restaurar el tablespace al modo normal.

2. Respaldar los archived redo logs:


Temporalmente suspender el proceso de archive
Determinar los archivos que existen en el directorio de archived redo logs.
Restaurar el proceso de archivo.
Respaldar los archived redo logs y luego borrarlos

3. Respaldar un control file utilizando el comando "alter database backup controlfile".

Veamos un ejemplo reducido dentro del svrmgrl:

alter tablespace SYSTEM begin backup;


!tar -cvf /dev/rmt/ohc/ /db01/oracle/DEMO/system01.dbf
alter tablespace SYSTEM end backup;

alter tablespace RBS begin backup;


!tar -rvf /dev/rmt/ohc/ /db01/oracle/DEMO/rbs01.dbf
alter tablespace RBS end backup;

archive log stop

--Registrar cuales arch existen ...


!FILES='ls /db01/oracle/arch/DEMO/arch*.dbf'; export FILES

archive log start

!tar -rvf /dev/rmt/0hc $FILES

!rm -f $FILES

alter database backup controlfile to


'/db01/oracle/DEMO/DEMOcontrolfile.bck';

!tar -rvf /dev/rmt/0hc /db01/oracle/DEMO/DEMOcontrolfile.bck


¿Cual método de respaldo utilizar?
Como siempre, no hay recetas mágicas, veamos una comparación entre ellos:

Método Tipo Características de Recuperación

Export Lógico Puede recuperar cualquier objeto de la


base de datos al momento en que fue
exportado.
Offline Backups Físico Puede recuperar la base de datos a su
estado al momento que fue bajada. Si la
base de datos está corriendo en modo
ARCHIVELOG, podrá luego ser
recuperado a cualquier punto en el tiempo.
Online Backups Físico Puede recuperar la base de datos a
cualquier punto en el tiempo.

Recuperación
Por ejemplo si se ha dañado un datafile específico:

1. Restaurar el archivo dañado desde el respaldo de la noche anterior


2. Montar la base de datos

Svrmgrl
Connect internal
Startup mount DEMO;

3. Dentro del svrmgrl, ejecutar

Recover database

esto nos preguntará por cada archived redo log, aunque existe una opción AUTO para
que la recuperación sea mas rápida.

4. Por último abrimos la base de datos:

Alter database open;

Tambien podemos recuperar una tabla que haya sido borrada accidentalmente
importandola desde un import:

Imp rh/rh tables=(emp) file=exp.dmp fromuser=rh touser=rh

Existen muchas opciones adicionales de recuperación que están fuera del alcance de
este libro pero que nos dan un nivel adicional de seguridad en caso de fallas.
Bloqueos
Oracle mantiene bloqueos a nivel de fila o tabla. Oracle nunca escalará un bloqueo hasta
nivel de tabla, aunque detecte que una gran mayoría de las filas en la tabla están siendo
bloqueadas. Consecuentemente, el programador debe decidir con anterioridad si bloque
la tabla completa o permite que cada fila sea bloqueada individualmente.

Existen dos parámetros en el init.ora que controlan el bloqueo: serializable=false y


row_locking=always. Estos valores por defecto nunca deben ser cambiados excepto en
casos raros.

Los distintos bloqueos que utiliza Oracle pueden subdivirse en:

Row Share Table Locks (RS), estos bloqueos son colocados cuando una transacción
SQL declara su intento de actualizar una tabla en modo row-share. Este tipo de
bloqueo le permitirá a otros queries actualizar filas en la tabla. Por ejemplo:
lock table customer in row share mode;

select customer_name
from customer
for update of customer;
Row Exclusive Table Locks (RX), estos bloqueos se ejecutan automáticamente contra
una tabla cuando se utiliza el comando Update, Delete o Insert contra una tabla.
Table Share Locks (S), este tipo de bloqueo es ejecutado cuando se utiliza el
comando LOCK TABLE. Este indica que la transacción pretende realizar
actualizaciones contra algunas de las filas en la tabla y previene a otras aplicaciones
ejecutarse.
Share Row Exclusive Table Locks (SRX), estos bloqueos se ejecutan cuando
utilizamos el comando LOCK TABLE xxxx IN SHARE ROW EXCLUSIVE MODE. Esto
previene a cualquier otra tarea de colocar cualquier LOCK TABLE hasta que la tarea
anterior sea completada, también previene cualquier intento de bloqueo a nivel de fila
Exclusive Table Locks(X), este el bloqueo más restrictivo. Este bloqueo previene todo
excepto queries contra la tabla afectada. Los bloqueos exclusivos son utilizados
cuando un programador desea tener control exclusivo sobre un conjunto de filas hasta
que su operación haya sido completada.

lock table customer in row exclusive mode nowait;


Para entender mejor como interactúan entre sí los diferentes tipos de bloqueo, veamos la
siguiente tabla, un valor NO, significa que no pueden existir al mismo momento.

RS RX S SRX X

RS YES YES YES YES NO


RX YES YES NO NO NO
S YES NO YES NO NO
SRX YES NO NO NO NO
X NO NO NO NO NO

Deadlocks
El escenario de bloqueos de Oracle asegura una integridad total de la base de datos y
que actualizaciones no sobreescriban actualizaciones anterior. Sin embargo, pagamos
una penalidad al utilizar bloqueos compartidos. En Oracle, cada bloqueo requiere 4 bytes
de RAM, por ejemplo un select que recuper 1000 filas requerirá 4000 bytes para manejo
de bloqueos.
También se pueden producir, lo que traducido a español sería algo así como el abrazo
mortal, deadlocks.

Tarea A Tarea B

LOCK MANAGER

1. La tarea A, ejecuta select * from emp; (1000 shared locks)


2. La tarea B ejecuta update emp set salary = salary * 1.1;
(espera que la tarea A libere sus shared locks)
3. La tarea A, ejecuta update emp set bonus_flag=1;
(la tarea A ahora espera por los bloqueos exclusivos seteados
por la tarea B, sin darse cuenta que la tarea A está esperando
por sus bloqueos)
La mayoría de los programadores no nos damos cuenta que muy comunmente los
deadlocks ocurren dentro de un índice. Es importante notar que un Select de una sóla fila
puede colocar más de un bloqueo. La fila recibe un bloqueo, pero cada nodo del índice
que contiene el valor para esta fila tambien recibe un bloqueo.

Cuando se ejecuta un Update o Delete también sucede lo mismo, se bloque la fila de


datos, pero muy probablemente se localicen bloqueos en los índices de esa tabla.

Debido a que la mayoría de las bases de datos comerciales sólo realizan un bloqueo de
una fila cuando necesitan bloquear una fila, podemos utilizar soluciones programáticas
para minimizar la cantidad de bloqueos utilizados durante tareas de gran actualización.
Por ejemplo, en Oracle, un programador puede utilizar Select .... For Update, para
bloquear explícitamente una fila o conjunto de filas antes de una operación de update.
Esto causará que la base de datos ejecute bloqueos exclusivos al momento de recuperar
la información y mantendrá este bloqueo hasta que la tarea sea grabada. Por ejemplo:

Select *
From emp
Where emp_name = 'JDURAN'
For update of salary;

Para actualizacion muy largas, podemos bloquear una tabla completa durante la duración
de la operación. Esto es útil cuando todas las filas de la tabla van a ser actualizadas
como en el siguiente ejemplo:

Lock table emp in exclusive mode nowait;

Update emp
Set salary = salary * 1.1;

Algunas veces una aplicación necesita actualizar todas las filas en una tabla pero no es
práctico bloquear toda la tabla. Una alternativa al update exclusivo, es utilizar la sentencia
FETCH de Oracle para bloquear un pequeño segmento de una tabla, realizar una
actualizacion, y luego liberarlas con un commit, o lo que es lo mismo hacer un cursor para
traer por ejemplo todos los empleados, para cada uno hacer un update contra un cursor
que haya sido hecho con la opción "for update".
Claro que este método, nos provoca otros problemas, como ¿qué pasa si detectamos un
problema luego de haber procesado cierta cantidad?, ya habría muchas transacciones
grabadas.
Para identificar bloqueos que están evitando que otras tareas sean completadas podemos
ejecutar el siguiente script:

COLUMN username format a10


COLUMN lockwait format a10
COLUMN sql_text format a80
COLUMN object_owner format a14
COLUMN object format a15

Select
b.username username,
c.sid sid,
c.owner object_owner,
c.object object,
b.lockwait,
a.sql_text sql
from v$sqltext a, v$session b, v$access c
where
a.address=b.sql_address
and a.hash_value=b.sql_hash_value
and b.sid=c.sid
and c.owner != 'SYS';

Existen varias vistas que a veces no están creadas, pero que su script se encuentra en
$ORACLE_HOME/rdbms/admin y se llama catblock.sql, los nombres de estas vistas son:

Dba_waiters
Dba_blockers
Dba_dml_locks
Dba_ddl_locks
Dba_locks
Laboratorio, auditoria, respaldo y recuperacion

Auditoría y seguridad
1. Ejecutar svrmgrl en unix
2. Connect internal
3. Startup
4. Exit
5. Sqlplus system/manager
6. Create profile prueba
Limit sessions_per_user 2
Cpu_per_session 10
Idle_time 60
Failed_login_attempts 5
Password_reuse_time 60
Password_reuse_max unlimited;
7. Select * from session_roles;
8. Select * from session_privs;
9. Create role account_creator;
10. Grant create session with admin option, create user, alter user to account_creator;
11. Create user juan identified by juan;
12. Grant account_creator to juan;
13. Connect juan/juan
14. Create user carlos identified by carlos;
15. Grant create session to carlos;
16. Create user ops$oracle identified externally;
17. Grant create session to ops$oracle;
18. Exit
19. Sqlplus /
20. Exit
21. Sqlplus system/manager
22. Select role, privilege, admin_option from role_sys_privs;
23. Select grantee, owner, table_name, grantor, privilege, grantable from dba_tab_privs
where grantee = 'SYSTEM';
24. Edite con vi el archivo initXXXX.ora, quite el simbolo "#" de la linea que dice
"audit_trail", luego salve el archivo.
25. Baje la base de datos y vuelvala a subir para que retome la nueva configuración
26. Sqlplus system/manager
27. Set linesize 120
28. Select
Substr(username, 1, 10) username,
Substr(os_username,1, 10) os_username,
Substr(owner, 1, 10) owner,
Substr(obj_name, 1, 30) obj_name,
Substr(action_name, 1, 30) action_name,
Timestamp,
From dba_audit_object
Where username = 'SYSTEM';
Save audit
29. create table x (linea varchar2(100));
30. audit all on x;
31. insert into x values 'askdlakdlads';
32. commit;
33. @audit;
34. exit

Respaldo y recuperación

35. exp userid=system/manager full=y file=curso.dmp


36. svrmgrl
37. connect internal
38. shutdown
39. exit
40. mkdir $ORACLE_HOME/respaldo
41. cd $ORACLE_HOME/dbs
42. tar -cvf $ORACLE_HOME/respaldo/copia.tar *.dbf
43. tar -rvf $ORACLE_HOME/respaldo/copia.tar init*.ora
44. tar -rvf $ORACLE_HOME/respaldo/copia.tar *control*
Bibliografía

Oracle 7 Server Concepts Manual, Oracle Corporation, 1997.


Oracle 7 Server Tuning, Oracle Corporation, 1997.
Oracle DBA Handbook, Kevin Loney, Osborne McGrawHill, 1998.
High Performance, Oracle Tuning, Don Burleson, Coriolis Group Books,
1998

Das könnte Ihnen auch gefallen