Tablas externas en Oracle9i

por Dave Moore

Aquí está un ejemplo paso a paso de como crear una tabla externa y ejecutar query's de esta fuente de datos dentro de Oracle, junto con una discusión de los usos prácticos para las tablas externas y su funcionamiento.

ORACLE9i tiene muchas nuevas características, y uno de mis favoritas es la capacidad de crear las tablas externas. Una tabla externa es una tabla donde la estructura se define dentro de la base de datos, aunque sus datos residen externamente en unos o más archivos en el sistema operativo (véase el cuadro 1). Las tablas externas son muy similares a las tablas regulares en Oracle, a menos que los datos no se almacenen en datafiles de Oracle y no sean manejados por la base de datos.

Cuadro 1: Estructura externa de la tabla en Oracle

Ejemplo


Este ejemplo comienza con la información de producto enumerada en una hoja de balance de Microsoft Excel (véase el cuadro 2). Los datos estan en formato (CSV) , D:\products\products.csv. La hoja de balance contiene tres columnas: Número, descripción, y precio del producto. Este archivo contiene los datos que preguntaremos de Oracle.

Cuadro 2: Los datos de producto en Excel.

Después de que se guarde el archivo de excel, la tarea siguiente es crear un objeto "DIRECTORIO" , que es donde esta fisicamente el archivo. Este DIRECTORIO se requiere para crear la tabla externa.

SQL> CREATE DIRECTORY PRODUCT_DIR AS 'd:\products';
Directory created.

Ahora la tabla externa es creada usando el comando de la CREATE TABLE :

create table products (
product_no number,
description varchar2(100),
price varchar2(20)
)
organization EXTERNAL (
type oracle_loader
default directory PRODUCT_DIR
access parameters
( records delimited by newline
badfile 'products.bad'
logfile 'products.log'
fields terminated by ','
)
location ('products.csv')
)
reject limit unlimited
/

La primera parte de la declaración de Create Table no tiene nada nuevo. Sin embargo, la parte siguiente de la declaración especifica ORGANIZATION EXTERNAL, que indica que esta tabla es una tabla externa. Esta parte de la declaración también especifica un tipo de Oracle_loader, el cual es solamente soportado por Oracle. Oracle_loader es realmente un tipo de objeto TYPE de Oracle definido en la base de datos para manejar los procesos.

También note que el directorio es parte de la declaración default directory PRODUCT_DIR; en esta linea se le indica a Oracle dónde encontrar los archivos.

La parte siguiente de la declaración especifica los parámetros del acceso, que deben parecer familiares a cualquier persona que ha utilizado SQL*Loader:

records delimited, especifica los caracteres que será utilizado para separar las filas.
badfile, especifica el archivo que el Oracle utilizará almacenar las filas rechazadas.
logfile, especifica el archivo que el Oracle utilizará almacenar la información del registro. La documentación de cualquier error será proporcionada en este archivo.
fields, especifica el separador distinguirá una columna de otra durante la carga.

Finalmente, se especifican la localización y el límite del rechazo:

location, la localización proporciona el nombre del archivo real al acceso. Si Oracle necesita tener acceso a archivos múltiples, pueden ser especificados como sigue:
location ('file1.dat', 'file2.dat')

reject limit, especifica el número de las filas que pueden ser rechazadas antes de que el comando devuelva un error. Si se alcanza este umbral, el error siguiente aparece al intentar tener acceso a la tabla:
ERROR at line 1:
ORA-29913: error in executing ODCIEXTTABLEFETCH callout
ORA-30653: reject limit reached
ORA-06512: at "SYS.ORACLE_LOADER", line 14
ORA-06512: at line 1

 

El DDL para crear la declaración funcionará incluso si el archivo no existe en el sistema. Por un lado, usted no sabrá si la tabla fue creada con éxito hasta que una sentecnia se ejecute contra la tabla. Inversamente, el archivo no tiene que existir cuando se crea la tabla. De hecho, el archivo puede venir e ir según lo necesitado, este esquema es absolutamente acostumbrado en ambientes de OLAP.

Una vez creada la tabla, si otro usuario intenta tener acceso a la tabla a este punto, este usuario recibirá el error:

SQL> select count(*) from dave.products;
select count(*) from dave.products
*
ERROR at line 1:
ORA-06564: object PRODUCT_DIR does not exist

Para prevenir este error, usted debe dar acceso de lectura y escritura en el directorio para cualquier usuario que desee consultar datos de la tabla. El conceder acceso de SELECT en la tabla permitirá que el objeto sea considerado, pero usted debe también conceder el acceso al objeto subyacente del directorio.

grant read, write on directory products_dir to alex;

Listing 1: Querying the table.

SQL> select product_no, substr(description,1,40) "Desc", Price from products;

PRODUCT_NO Desc PRICE
---------- -------------------------------------- ---------------
12300 Robin Yount Autographed Baseball $29.99
12301 George Brett Autographed Baseball $19.99
12302 Dale Murphy Autographed Baseball $19.99
12303 Paul Molitor Autographed Baseball $19.99
12304 Nolan Ryan Autographed Baseball $19.99
12305 Craig Biggio Autographed Baseball $19.99
12306 Jeff Bagwell Autographed Baseball $19.99
12307 Barry Bonds Autographed Baseball $19.99
12308 Mark McGuire Autographed Baseball $19.99
12309 Sammy Sosa Autographed Baseball $19.99
12310 Jeff Kent Autographed Baseball $19.99
12311 Roger Clemens Autographed Baseball $19.99
12312 Goose Gossage Autographed Baseball $19.99
12313 Derek Jeter Autographed Baseball $19.99

14 rows selected.

El acceso de lectura/grabación significa que en Oracle estará permitido escribir a ese directorio cuando necesita poner al día el logfile o badfile. Como usuario del Sistema Operativo, usted no tiene acceso a esos archivos en el sistema operativo a menos que su identificación tenga privilegios apropiados; consecuentemente, la seguridad no se compromete.

Después de crear la tabla externa y de conceder privilegios, la tabla se puede utilizar como cualquier otra tabla (véase el listado 1).

La tabla externa se puede utilizar como substituto de SQL*Loader y una tabla regular se puede utilizar para llevar a cabo sus datos:

INSERT INTO PROD.PRODUCTS AS SELECT * from DAVE.PRODUCTS;

Los datos que estaban en excel se cargan en Oracle, lo que permite que sea sostenido y que se realice mejor que una tabla externa.

Limitaciones

Las tablas externas en Oracle9i tienen las siguientes limitaciones:

Son inalterables, así que ninguna operacion de manipulación de datos (DML) (tales como insert, update o delete) se pueden realizar contra ellos. También, no se pueden definir índices en la tabla. Oracle tiene planeado apoyar la escritura en estas tablas en un lanzamiento futuro.

No soporta archivos más grandes de 2GB. Si usted procura tener acceso a un archivo más grande que 2GB, Oracle falla con el siguiente error :

KUP - 04039: unexpected error while trying to find file
<file name> in director <directory name>

Ciertos comandos contra la tabla, por ejemplo ANALYZE, fallarán.


SQL> analyze table products compute statistics;
analyze table products compute statistics

*
ERROR at line 1:
ORA-30657: operation not supported on external organized
Table

Esta limitación es importante porque la mayoría del DBAs tiene escrituras que restauren regularmente la estadística del objeto basada en un esquema. Si usted intenta generar estadística en una tabla externa, el comando fallará.

Los datos en tablas externas no se sostienen como parte de rutinas de Backup regular de Oracle, porque están fuera del alcance de la base de datos.

Funcionamiento

Uno espera que el núcleo de Oracle incurra en más gastos indirectos al procesar las tablas externas. Oracle TYPE and TYPE BODY named SYS.ORACLE_LOADER existen en la base de datos y procesan todas las declaraciones que tienen acceso a las tablas externas. Este proceso aumenta los gastos indirectos para tener acceso a los datos, y cuando está comparado a una tabla regular es muchas veces más lento. Oracle debe traer y realizar las tareas que no realiza (por ejemplo las conversiones, manejando rechazamientos, y registrándolos) y es normalmente por lo tanto, perceptiblemente más lento.

Experimenté con el funcionamiento de tablas externas creando una tabla interna con los datos exactos como el externo:

SQL> create table products_internal as select * from
products;

Table created.

La tabla contuvo 5.292 filas, con los mismos datos que en la hoja de balance. La tabla interna no tenía índices o llaves primarias definidas. De acuerdo con la escritura demostrada en el listado 2, la tabla interna era constantemente 8-10 veces más rápida en tener acceso que la externa.

Recomendación, las tablas externas se deben utilizar como medios de carga de datos en las tablas internas y no se deben utilizar como fuente de datos externa.

Listado 2: El acceso a la tabla interna es perceptiblemente más rápido que a la tabla externa.

set term off
col a new_value start
select dbms_utility.get_time() a from dual;
select count(*) from products_internal where product_no = 12313;
col b new_value stop
select dbms_utility.get_time() b from dual;
col c new_value answer
select (&stop - &start) c from dual;
col d new_value start_ext
select dbms_utility.get_time() d from dual;
select count(*) from products where product_no = 12313;
col e new_value stop_ext
select dbms_utility.get_time() e from dual;
col f new_value answer_ext
select (&stop_ext - &start_ext) f from dual;
col ans form 999
col ans_ext form 999
set term on
prompt
prompt
select 'Internal Table Execution Time in ms ', &answer ans
from dual;
select 'External Table Execution Time in ms ', &answer_ext ans_ext
from dual;

Tomando las siguientes acciones, usted puede reducir al mínimo los gastos indirectos usados al procesar una tabla externa:

Utilice la cláusula PARALLEL cuando cree la tabla. Este valor indica el número de procesadores que serán utilizados para procesar los datafiles y dividirá los archivos en porciones para que puedan ser procesadas por separado.
Utilice datatypes en Oracle, ya que emparejará las cualidades físicas de los datos, eliminando la conversión de datos costosa.
Utilice valores fijos cuando sea posible, incluyendo:
Fixed-width character sets
Fixed-length fields
Fixed-length records

La cláusula RECORDS FIXED se enumera bajo parámetros del acceso y requiere la definición de campos. En el siguiente ejemplo , la línea de datos tiene 40 bytes de largo, más un byte para la nueva línea. Los nombres de campo deben ser iguales que los nombres de la columna a los cuales corresponden.

RECORDS FIXED 41
FIELDS
(
emp_first_name char(20)
emp_last_name char(20)
)

Utilice delimitadores de un solo caracter, y utilice los mismos juegos de caracteres que utiliza la base de datos.
Reduzca al mínimo los rechazos puesto que Oracle realiza más I/O para cada.


Usos Prácticos

Las tablas externas tienen muchos usos prácticos, que pondré en dos categorías: proceso de negocio y administración de la base de datos.

Desde el punto de vista de negocio-proceso, las tablas externas responden a una necesidad vital en un ambiente de dato-almacenamiento, en el cual la extracción, transformación, y los procesos de la carga son comunes. Las tablas externas hacen innecesario que los usuarios creen las tablas temporales durante estos procesos, reduciendo el espacio requerido y el riesgo de trabajos fallados. Las tablas externas se pueden utilizar en vez de las tablas temporales y de utilidades como SQL*Loader. También proporcionan una manera fácil para que las compañías puedan cargar diversas fuentes de información en Oracle desde Excel, ACT!, o Access.

En cuanto a la administración de la base de datos . Si deseo supervisar esos archivos que reviso con mas frecuencia como alert.log e init.ora desde un prompt SQL>. Entonces puedo utilizar comandos del SQL para preguntar datos del archivo y de especificar criterios para un proceso más sofisticado. Un ejemplo de crear una tabla externa para revisar al registro alerta (alert.log ) :

create directory BDUMP AS 'd:\oracle9i\admin\PROD\bdump';
create table alert_log (text varchar2(200))
organization EXTERNAL (
type oracle_loader
default directory BDUMP
access parameters
( records delimited by newline
badfile 'dave.bad'
logfile 'dave.log'
fields terminated by ' '
)
location ('PRODALRT.LOG')
)
reject limit unlimited;

Listado 3: La opinión de DBA_EXTERNAL_LOCATIONS.

SQL> desc dba_external_locations;
Name Null? Type
----------------------------------------- -------- ----------------
OWNER NOT NULL VARCHAR2(30)
TABLE_NAME NOT NULL VARCHAR2(30)
LOCATION VARCHAR2(4000)
DIRECTORY_OWNER CHAR(3)
DIRECTORY_NAME VARCHAR2(30)

Administración De la Base de datos

Es importante saber qué vistas en Oracle contienen la información que pertenece a las tablas externas. La vista DBA_TABLES demuestra las tablas externas y tiene un valor de 0 para PCT_FREE, PCT_USED, INI_TRANS, y MAX_TRANS. El resto de las columnas del almacenaje en la vista son nulas. Los scripts que utiliza esta vista para determinar problemas debe ser actualizado para tener acceso a DBA_EXTERNAL_TABLES. Esta vista contiene todos los parámetros que usted especificó cuando usted creó la tabla externa.

Otra vista útil es DBA_EXTERNAL_ LOCATIONS, que proporciona una manera rápida de ver qué archivos están registrados en la base de datos (véase el listado 3).

---
Dave Moore es arquitecto del producto en BMC Austin, TX. He's also a Java and PL/SQL developer, Oracle DBA and author of Oracle Utilities by Rampant Tech Press