07.05.2013 Views

metodos de optimizacion de consultas para el lenguaje ... - Blearning

metodos de optimizacion de consultas para el lenguaje ... - Blearning

metodos de optimizacion de consultas para el lenguaje ... - Blearning

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

UNIVERSIDAD DE SANTIAGO DE CHILE<br />

FACULTAD DE CIENCIAS<br />

DEPARTAMENTO DE MATEMATICA Y CIENCIA DE LA COMPUTACION<br />

METODOS DE OPTIMIZACION DE CONSULTAS PARA EL<br />

LENGUAJE SQL.<br />

MARIO CISTERNA NEIRA<br />

SANTIAGO - CHILE<br />

2002


TABLA DE CONTENIDOS<br />

DEFINICIÓN DEL PROBLEMA...........................................................................4<br />

ESTRUCTURA DEL LIBRO..................................................................................6<br />

CAPÍTULO 1. MODELO DE DATOS RELACIONAL.....................................8<br />

1.1. INTRODUCCIÓN. ................................................................................................8<br />

1.2. IMPLEMENTACIONES RELACIONALES................................................................9<br />

1.3. CONCEPTOS GENERALES. ................................................................................10<br />

CAPÍTULO 2. LENGUAJES DE CONSULTA PARA EL MODELO<br />

RELACIONAL. ..........................................................................16<br />

2.1. INTRODUCCIÓN. ..............................................................................................16<br />

2.2. ALGEBRA RELACIONAL. ..................................................................................17<br />

2.3. CÁLCULO RELACIONAL DE TUPLAS. ................................................................23<br />

2.4. SQL COMO LENGUAJE DE CONSULTAS RELACIONALES. ..................................27<br />

CAPÍTULO 3. SISTEMAS DE GESTIÓN DE BASES DE DATOS<br />

RELACIONALES. .....................................................................31<br />

3.1. INTRODUCCIÓN. ..............................................................................................31<br />

3.2. TRANSACCIONES, CONCURRENCIA Y RECUPERACIÓN......................................33<br />

3.3. TIPOS DE SGBD..............................................................................................40<br />

CAPÍTULO 4. INTRODUCCIÓN AL PROCESAMIENTO DE<br />

CONSULTAS, EL ENFOQUE DE SYSTEM R....................48<br />

4.1. INTRODUCCIÓN. ..............................................................................................48<br />

4.2. EL OPTIMIZADOR DE SYSTEM R. .....................................................................51<br />

CAPÍTULO 5. OPTIMIZACIÓN DE CONSULTAS, FUNDAMENTO<br />

TEÓRICO. ..................................................................................69<br />

5.1. INTRODUCCIÓN. ..............................................................................................69<br />

5.2. INFORMACIÓN DEL CATÁLOGO........................................................................70<br />

5.3. MEDIDAS DE COSTO. .......................................................................................72<br />

5.4. EVALUACIÓN DE EXPRESIONES. ......................................................................95<br />

5.5. ORDENES DE JOIN. ........................................................................................107<br />

5.6. ELECCIÓN DE LOS PLANES DE EVALUACIÓN. .................................................123<br />

CAPÍTULO 6. EL OPTIMIZADOR DE CONSULTAS DE SYBASE<br />

ADAPTIVE SERVER ENTERPRISE, UN EJEMPLO<br />

PRÁCTICO...............................................................................128<br />

6.1. INTRODUCCIÓN. ............................................................................................128<br />

6.2. ANÁLISIS DE LA CONSULTA. .........................................................................129<br />

1


6.3. SELECCIÓN DE ÍNDICES. ................................................................................135<br />

6.4. SELECCIÓN DE LOS ORDENES DE JOIN............................................................137<br />

6.5. USO DE TABLAS TEMPORALES.......................................................................147<br />

6.6. SELECCIÓN DEL PLAN....................................................................................148<br />

6.7. RESUMEN......................................................................................................152<br />

RESUMEN Y CONCLUSIONES........................................................................154<br />

RESUMEN.............................................................................................................154<br />

CONCLUSIONES....................................................................................................157<br />

BIBLIOGRAFÍA...................................................................................................160<br />

APÉNDICES. 162<br />

A. SINTAXIS DE SQL..................................................................162<br />

A.1. DEFINICIONES DE DATOS EN SQL.................................................................162<br />

A.2. MANIPULACIÓN DE DATOS EN SQL..............................................................167<br />

B. INDICES B+..............................................................................178<br />

C. MÉTODOS DE ALMACENAMIENTO DE DATOS...........181<br />

C.1. DISCOS MAGNÉTICOS...................................................................................182<br />

2


TABLA DE TABLAS<br />

TABLA 2-1 - OPERADORES DEL ALGEBRA RELACIONAL ........................................................17<br />

TABLA 4-1 - FACTORES DE SELECCIÓN PARA CAMINOS DE ACCESO A RELACIONES SIMPLES.58<br />

TABLA 4-2 - FÓRMULAS DE COSTO PARA CAMINOS DE ACCESO A RELACIONES SIMPLES........61<br />

TABLA 5-1 - INFORMACIÓN DEL CATÁLOGO PARA RELACIONES SIMPLES. .............................71<br />

TABLA 5-2 - INFORMACIÓN DEL CATÁLOGO PARA ÍNDICES DE RELACIONES..........................72<br />

TABLA 5-3 - REGLAS DE EQUIVALENCIA PARA EXPRESIONES RELACIONALES......................104<br />

TABLA A-1 - TIPOS DE DATOS DE SQL................................................................................164<br />

TABLA DE ALGORITMOS<br />

ALGORITMO 5-1 - JOIN EN BUCLES ANIDADOS.......................................................................83<br />

ALGORITMO 5-2 - JOIN EN BUCLES ANIDADOS POR BLOQUES.................................................84<br />

ALGORITMO 5-3 - JOIN POR MEZCLA. ....................................................................................86<br />

ALGORITMO 5-4 - JOIN POR ASOCIACIÓN...............................................................................89<br />

ALGORITMO 5-5 - JOIN ENCAUZADO......................................................................................99<br />

TABLA DE FIGURAS<br />

FIGURA 2-1 - ESQUEMA DE RELACIONES DE EJEMPLO...........................................................18<br />

FIGURA 4-1 - PASOS EN EL PROCESAMIENTO DE UNA CONSULTA SQL...................................50<br />

FIGURA 5-1 - COMPORTAMIENTO DEL ALGORITMO DE SIMULACIÓN DE COCCIÓN ..............116<br />

FIGURA 5-2 - EJEMPLO DEL PRINCIPIO DE SELECCIÓN PARA EL ALGORITMO GENÉTICO PARA LA<br />

OPTIMIZACIÓN DE ORDENES DE JOIN ............................................................................120<br />

FIGURA 5-3 - EJEMPLO DEL PRINCIPIO DE COMBINACIÓN PARA EL ALGORITMO GENÉTICO<br />

PARA LA OPTIMIZACIÓN DE ORDENES DE JOIN..............................................................121<br />

FIGURA 5-4 - UN PLAN DE EVALUACIÓN DE EJEMPLO ..........................................................123<br />

3


Definición <strong>de</strong>l problema.<br />

En Bases <strong>de</strong> datos r<strong>el</strong>acionales <strong>el</strong> <strong>lenguaje</strong> <strong>de</strong> <strong>consultas</strong> SQL es lo más<br />

utilizado por <strong>el</strong> común <strong>de</strong> los programadores y <strong>de</strong>sarrolladores <strong>para</strong> obtener<br />

información <strong>de</strong>s<strong>de</strong> la Base <strong>de</strong> datos. La complejidad que pue<strong>de</strong>n alcanzar algunas<br />

<strong>consultas</strong> pue<strong>de</strong> ser tal, que <strong>el</strong> diseño <strong>de</strong> una consulta pue<strong>de</strong> tomar un tiempo<br />

consi<strong>de</strong>rable, obteniendo no siempre una respuesta optima.<br />

Dada una consulta, generalmente existen varias maneras <strong>de</strong> calcular la<br />

respuesta. En SQL una consulta pue<strong>de</strong> expresarse <strong>de</strong> distintas maneras, todas<br />

<strong>el</strong>las diferentes, como lo expresa C. Date en [Date98], cada una <strong>de</strong> las formas<br />

sugiere una estrategia <strong>para</strong> encontrar la respuesta y por lo tanto algunas pue<strong>de</strong>n<br />

ser más optimas que otras.<br />

El problema que se plantea entonces es, <strong>el</strong> encontrar la manera más<br />

apropiada <strong>de</strong> resolver la consulta, sin que, <strong>el</strong> proceso <strong>de</strong> <strong>de</strong>terminar este resultado<br />

exceda un tiempo razonable y un gasto <strong>de</strong> recursos adicional.<br />

Como respuesta a este problema, nace <strong>el</strong> concepto <strong>de</strong> optimización <strong>de</strong><br />

<strong>consultas</strong>. El objetivo principal <strong>de</strong> este proceso es, encontrar o bien la mejor<br />

alternativa <strong>para</strong> solucionar la consulta, o <strong>de</strong> lo contrario, la alternativa que mejor<br />

cumpla las características <strong>de</strong> eficiencia, entre las estudiadas, cuando no sea<br />

posible estudiarlas todas.<br />

Este proceso tiene que ser lo bastante rápido como <strong>para</strong> que sea<br />

conveniente <strong>para</strong> <strong>el</strong> motor efectuar este cálculo sin afectar <strong>el</strong> rendimiento en la<br />

construcción <strong>de</strong>l resultado <strong>de</strong> la consulta.<br />

4


Uno <strong>de</strong> los primeros estudios r<strong>el</strong>ativo a optimización <strong>de</strong> <strong>consultas</strong> <strong>para</strong> SQL<br />

se hizo sobre <strong>el</strong> prototipo <strong>de</strong> un motor <strong>de</strong> base <strong>de</strong> datos r<strong>el</strong>acional <strong>de</strong>sarrollado por<br />

IBM llamado “system R”, en los laboratorios <strong>de</strong> San José (California) a mediados<br />

<strong>de</strong> la década <strong>de</strong> 1970. Este estudio proporcionaría las bases <strong>para</strong> la construcción<br />

<strong>de</strong> la mayoría <strong>de</strong> los optimizadores <strong>para</strong> motores <strong>de</strong> base <strong>de</strong> datos r<strong>el</strong>acionales <strong>de</strong><br />

or<strong>de</strong>n comercial en la actualidad.<br />

Entre otras cosas, este estudio propone la <strong>de</strong>scomposición <strong>de</strong>l<br />

procesamiento <strong>de</strong> una consulta SQL en 4 fases: <strong>el</strong> análisis sintáctico (parsing), la<br />

optimización, la generación <strong>de</strong> código y la ejecución <strong>de</strong> la consulta.<br />

Se entien<strong>de</strong> entonces como proceso <strong>de</strong> optimización <strong>de</strong> <strong>consultas</strong> al<br />

conjunto <strong>de</strong> técnicas, algoritmos y reglas que le permiten, al motor <strong>de</strong> base <strong>de</strong><br />

datos, <strong>el</strong>egir una alternativa entre varias con la cual pueda rescatar los datos <strong>de</strong> la<br />

manera más optima.<br />

El objetivo principal <strong>de</strong> este trabajo es Investigar este proceso y <strong>de</strong>v<strong>el</strong>arlo,<br />

con la finalidad <strong>de</strong> que <strong>de</strong>je <strong>de</strong> ser algo <strong>de</strong>sconocido <strong>para</strong> quienes interactúan con<br />

Sistemas <strong>de</strong> Gestión <strong>de</strong> bases <strong>de</strong> datos r<strong>el</strong>acionales.<br />

La i<strong>de</strong>a <strong>de</strong> este trabajo es que le sirva <strong>de</strong> apoyo tanto al diseñador <strong>de</strong> base<br />

<strong>de</strong> datos r<strong>el</strong>acionales, como a los <strong>de</strong>sarrolladores que ejecutan <strong>consultas</strong>,<br />

quienes, al enten<strong>de</strong>r mas <strong>de</strong> cerca <strong>el</strong> proceso <strong>de</strong> optimización <strong>de</strong> <strong>consultas</strong><br />

puedan evitar los errores más comunes, que a la larga llevan muchas veces al<br />

fracaso en la construcción e implementación <strong>de</strong> sistemas <strong>de</strong> Información sobre<br />

bases <strong>de</strong> datos r<strong>el</strong>acionales.<br />

5


Estructura <strong>de</strong>l libro.<br />

El Capítulo 1 introduce <strong>el</strong> mo<strong>de</strong>lo r<strong>el</strong>acional <strong>de</strong> datos, <strong>el</strong> cual es la base<br />

<strong>para</strong> <strong>el</strong> <strong>de</strong>sarrollo <strong>de</strong> este trabajo, se presentará un marco <strong>de</strong> trabajo teórico sobre<br />

<strong>el</strong> cual <strong>de</strong>sarrollar <strong>el</strong> problema.<br />

El Capítulo 2 trata sobre los distintos <strong>lenguaje</strong>s <strong>para</strong> recuperación <strong>de</strong> datos<br />

que existen <strong>para</strong> <strong>el</strong> mo<strong>de</strong>lo r<strong>el</strong>acional, otorgando un énfasis especial sobre <strong>el</strong><br />

álgebra r<strong>el</strong>acional y <strong>el</strong> cálculo r<strong>el</strong>acional <strong>de</strong> tuplas, fundamentales <strong>para</strong> la<br />

presentación <strong>de</strong> SQL como <strong>lenguaje</strong> <strong>de</strong> <strong>consultas</strong>.<br />

El procesamiento <strong>de</strong> una consulta SQL <strong>de</strong>pen<strong>de</strong>rá en gran medida <strong>de</strong> la<br />

implemetación r<strong>el</strong>acional en la cual se ejecute, por lo tanto, <strong>el</strong> Capítulo 3 presenta<br />

la conceptualización sobre Sistemas <strong>de</strong> Gestión <strong>de</strong> base <strong>de</strong> datos r<strong>el</strong>acionales<br />

(SGBD), a modo <strong>de</strong> explicación <strong>de</strong> cómo se logran implementaciones r<strong>el</strong>acionales<br />

<strong>de</strong>l mo<strong>de</strong>lo, en este capítulo se explicarán brevemente conceptos tales como<br />

transacciones, concurrencia y repcuperación <strong>de</strong> datos.<br />

El Capítulo 4 Introduce al tema <strong>de</strong>l procesamiento <strong>de</strong> <strong>consultas</strong>, <strong>para</strong> tales<br />

efectos se presenta <strong>el</strong> estudio <strong>de</strong>l optimizador <strong>de</strong> <strong>consultas</strong> <strong>de</strong> System R. Este<br />

SGBD se consi<strong>de</strong>ra una <strong>de</strong> las primeras implementaciones r<strong>el</strong>acionales y motivo<br />

<strong>de</strong> investigación tanto como fundamento y guia <strong>para</strong> la construcción <strong>de</strong> la mayoría<br />

<strong>de</strong> los optimizadores r<strong>el</strong>acionales comerciales actuales. El estudio <strong>de</strong> este caso<br />

introduce conceptos como medidas <strong>de</strong> costo, caminos <strong>de</strong> acceso y utilización <strong>de</strong><br />

heurísticas <strong>de</strong>ntro <strong>de</strong> un optimizador.<br />

El Capítulo 5 <strong>de</strong>sarrolla <strong>el</strong> fundamento teórico <strong>de</strong>l libro, estudia en profundidad <strong>el</strong><br />

proceso <strong>de</strong> optimización <strong>de</strong> <strong>consultas</strong> SQL. Este capítulo explica como los<br />

optimizadores <strong>de</strong>terminan sus medidas <strong>de</strong> costo y en que información se basan<br />

6


<strong>para</strong> estos cálculos; como se produce la evaluación <strong>de</strong> expresiones y como<br />

<strong>de</strong>terminar los or<strong>de</strong>nes <strong>de</strong> Join.<br />

Dado que este trabajo no tiene asociado un <strong>de</strong>sarrollo práctico <strong>de</strong>l tema, <strong>el</strong><br />

Capítulo 6 presenta un ejemplo <strong>de</strong> cómo trabaja en la práctica un optimizador <strong>de</strong><br />

<strong>consultas</strong> <strong>para</strong> un SGBD comercial, <strong>para</strong> tales efectos se presenta <strong>el</strong> caso <strong>de</strong><br />

Sybase Adaptive Server Enterprise (ASE). Este capítulo llevará al lector a<br />

enten<strong>de</strong>r que existe una correspon<strong>de</strong>ncia entre lo presentado en <strong>el</strong> Capítulo 4, lo<br />

explicado en <strong>el</strong> Capítulo 5, y como se logra esto en la práctica.<br />

7


Capítulo 1. Mo<strong>de</strong>lo <strong>de</strong> Datos R<strong>el</strong>acional<br />

1.1. Introducción.<br />

El objetivo <strong>de</strong> todo mo<strong>de</strong>lo <strong>de</strong> datos es proveer conceptos y estructuras <strong>de</strong><br />

datos capaces <strong>de</strong> interpretar los aspectos r<strong>el</strong>evantes que existen en una<br />

<strong>de</strong>terminada parc<strong>el</strong>a <strong>de</strong>l mundo real. Esto se logra mediante un conjunto bien<br />

<strong>de</strong>finido <strong>de</strong> estructuras, operadores y restricciones que actúan sobre dichas<br />

estructuras.<br />

El Mo<strong>de</strong>lo R<strong>el</strong>acional correspon<strong>de</strong> a un enfoque científico y tecnológico que<br />

surgió entre la década <strong>de</strong> 1960 y la década <strong>de</strong> 1970. Su estrategia <strong>de</strong> abstracción<br />

se basa en hacer una representación tabular <strong>de</strong> los objetos y sus asociaciones<br />

entre <strong>el</strong>los. Sin embargo, este enfoque tabular que se sustenta en la teoría <strong>de</strong> las<br />

r<strong>el</strong>aciones matemáticas no permite diferenciar entre los tipos <strong>de</strong> entidad y los tipos<br />

<strong>de</strong> r<strong>el</strong>ación, lo que constituye una pérdida semántica significativa con respecto a<br />

su antecesor, <strong>el</strong> mo<strong>de</strong>lo <strong>de</strong> Entidad-R<strong>el</strong>ación.<br />

Por otra parte, la representación tabular <strong>de</strong> la información y los mecanismos<br />

utilizados <strong>para</strong> establecer vínculos entre las tablas que se representan <strong>de</strong> objetos<br />

r<strong>el</strong>acionados han contribuido enormemente a su masificación, a tal punto que en la<br />

actualidad, <strong>el</strong> Mo<strong>de</strong>lo R<strong>el</strong>acional es un estándar <strong>de</strong> hecho en los que se<br />

construyen los SGBD 1 comerciales.<br />

Es importante notar que <strong>el</strong> mo<strong>de</strong>lo r<strong>el</strong>acional es un mo<strong>de</strong>lo basado en <strong>el</strong><br />

pap<strong>el</strong> y que no todas sus características son implementadas en los SGBD, como a<br />

1 SGBD : Sistemas <strong>de</strong> Gestión <strong>de</strong> Bases <strong>de</strong> datos.<br />

8


su vez muchas implementaciones tienen más características que las que<br />

contempla <strong>el</strong> mo<strong>de</strong>lo.<br />

1.2. Implementaciones R<strong>el</strong>acionales.<br />

Una implementación <strong>de</strong>l mo<strong>de</strong>lo r<strong>el</strong>acional <strong>de</strong>be soportar todas las<br />

facilida<strong>de</strong>s prescritas por <strong>el</strong> mo<strong>de</strong>lo, sin embargo existen algunas características a<br />

las cuales no hace referencia <strong>el</strong> mo<strong>de</strong>lo <strong>de</strong> datos r<strong>el</strong>acional, <strong>de</strong>ntro <strong>de</strong> estas se<br />

incluyen operaciones aritméticas, funciones agregadas, actualizaciones explícitas,<br />

modificaciones, <strong>el</strong>iminaciones, etc. Para esto <strong>el</strong> Mo<strong>de</strong>lo r<strong>el</strong>acional incluye un<br />

núcleo <strong>de</strong> funciones que <strong>de</strong>ben ser incorporadas en un SGBD.<br />

Sin embargo existe una distinción entre las implementaciones consi<strong>de</strong>radas<br />

r<strong>el</strong>acionales y los que no lo son en su totalidad (Pseudo-R<strong>el</strong>acionales). Estas<br />

últimas se pue<strong>de</strong>n clasificar como sigue:<br />

• Tabular : Un SGBD Tabular es una implementación <strong>de</strong> una Base <strong>de</strong> datos<br />

r<strong>el</strong>acional que soporta las estructuras <strong>de</strong> datos tabulares (tablas), pero no<br />

los operadores <strong>de</strong> niv<strong>el</strong> <strong>de</strong> conjuntos.<br />

• R<strong>el</strong>acional Mínimo: Un SGBD Mínimamente r<strong>el</strong>acional es una<br />

implementación <strong>de</strong> bases <strong>de</strong> datos r<strong>el</strong>acionales que soporta sólo tablas, los<br />

operadores <strong>de</strong> s<strong>el</strong>ección, proyección y <strong>el</strong> operador JOIN (pero no los otros<br />

operadores r<strong>el</strong>acionales).<br />

• R<strong>el</strong>acional Completo: Un SGBD Completamente r<strong>el</strong>acional es una<br />

implementación <strong>de</strong> bases <strong>de</strong> datos r<strong>el</strong>acionales que soporta sólo tablas y<br />

todos los operadores <strong>de</strong>l álgebra r<strong>el</strong>acional.<br />

9


• R<strong>el</strong>acional : Un SGBD R<strong>el</strong>acional es una implementación <strong>de</strong> Bases <strong>de</strong><br />

datos r<strong>el</strong>acionales que soporta todos los aspectos <strong>de</strong>l mo<strong>de</strong>lo r<strong>el</strong>acional<br />

incluidos los dominios y las dos reglas generales <strong>de</strong> Integridad (que se<br />

explicarán más a<strong>de</strong>lante, en <strong>el</strong> punto 1.3.12).<br />

1.3. Conceptos generales.<br />

1.3.1. Datos Atómicos<br />

Todos los valores <strong>de</strong> datos en <strong>el</strong> mo<strong>de</strong>lo r<strong>el</strong>acional son atómicos. Esto<br />

implica que cada posición <strong>de</strong> fila-columna en cada tabla siempre tiene sólo un<br />

dato, y nunca un conjunto <strong>de</strong> valores.<br />

1.3.2. Tuplas<br />

Una tupla <strong>de</strong> una r<strong>el</strong>ación o <strong>de</strong> una tabla correspon<strong>de</strong> a una fila <strong>de</strong> aqu<strong>el</strong>la<br />

tabla. Las tuplas están comúnmente <strong>de</strong>sor<strong>de</strong>nadas puesto que matemáticamente<br />

una r<strong>el</strong>ación se <strong>de</strong>fine como un conjunto y no como una lista. No Existen tuplas<br />

duplicadas en una r<strong>el</strong>ación o tabla dado <strong>el</strong> hecho <strong>de</strong> que una r<strong>el</strong>ación es un<br />

conjunto y los conjuntos por <strong>de</strong>finición no permiten <strong>el</strong>ementos duplicados. Un<br />

corolario importante en este punto es que la llave primaria siempre existe dada la<br />

condición <strong>de</strong> unicidad <strong>de</strong> las tuplas, por lo tanto, como mínimo la combinación <strong>de</strong><br />

todos los atributos <strong>de</strong> una tabla pue<strong>de</strong> servir <strong>para</strong> la conformación <strong>de</strong> la llave<br />

primaria, sin embargo usualmente no es necesario incluir todos los atributos,<br />

comúnmente algunas combinaciones mínimas son suficientes.<br />

1.3.3. Dominios.<br />

Un dominio se <strong>de</strong>fine como un conjunto <strong>de</strong> valores <strong>de</strong>l mismo tipo. Por<br />

ejemplo <strong>el</strong> dominio que correspon<strong>de</strong> a la edad <strong>de</strong> una persona (en años) se pue<strong>de</strong><br />

10


<strong>de</strong>finir como <strong>el</strong> conjunto <strong>de</strong> todos los valores <strong>de</strong> números posibles <strong>de</strong> eda<strong>de</strong>s, por<br />

ejemplo <strong>de</strong>s<strong>de</strong> 0 hasta 120. Siempre y cuando dos atributos tomen sus valores <strong>de</strong>l<br />

mismo dominio estos pue<strong>de</strong>n ser com<strong>para</strong>dos aunque pertenezcan a distintas<br />

tablas. Los dominios son especificados como parte <strong>de</strong> la <strong>de</strong>finición <strong>de</strong> los datos,<br />

estos pue<strong>de</strong>n ser simples o compuestos. Un dominio compuesto se <strong>de</strong>fine como<br />

<strong>el</strong> producto <strong>de</strong> alguna colección <strong>de</strong> dominios simples. Por ejemplo la fecha es<br />

producto <strong>de</strong> <strong>el</strong> día, <strong>el</strong> mes y <strong>el</strong> año, don<strong>de</strong> <strong>el</strong> mes es <strong>el</strong> dominio simple <strong>de</strong> 1 a 12 y<br />

así sucesivamente).<br />

1.3.4. Atributos.<br />

Un atributo <strong>de</strong> una r<strong>el</strong>ación o <strong>de</strong> una tabla correspon<strong>de</strong> a una columna <strong>de</strong> la<br />

tabla. Los atributos están <strong>de</strong>sor<strong>de</strong>nados y se referencian por nombres y no por la<br />

posición que ocupan. Esto significa que no se pue<strong>de</strong>, por ejemplo, hacer<br />

referencia al tercer atributo <strong>de</strong> una r<strong>el</strong>ación. Todos los valores <strong>de</strong> los atributos son<br />

atómicos y una r<strong>el</strong>ación que satisfaga esta condición se llama r<strong>el</strong>ación<br />

normalizada. Un atributo extrae sus valores <strong>de</strong>s<strong>de</strong> un dominio simple.<br />

Formalmente, un atributo es una función que se <strong>de</strong>fine entre un Dominio y<br />

un <strong>de</strong>terminado tipo <strong>de</strong> Entidad <strong>de</strong> la base <strong>de</strong> datos. Dicha función asocia una<br />

ocurrencia <strong>de</strong> Tipo <strong>de</strong> Entidad con un <strong>de</strong>terminado <strong>el</strong>emento <strong>de</strong>l dominio.<br />

1.3.5. Esquema <strong>de</strong> R<strong>el</strong>ación.<br />

Un esquema <strong>de</strong> r<strong>el</strong>ación es <strong>el</strong> conjunto que i<strong>de</strong>ntifica todas las propieda<strong>de</strong>s<br />

(Atributos) <strong>de</strong> un objeto. Se representa por <strong>el</strong> conjunto :<br />

{ A A , A A }<br />

E = ,......<br />

1,<br />

2 3<br />

don<strong>de</strong> , i = 1,...<br />

n correspon<strong>de</strong> a un atributo y n <strong>el</strong> número <strong>de</strong> atributos <strong>de</strong><br />

A i<br />

interés <strong>de</strong>l objeto.<br />

n<br />

11


1.3.6. R<strong>el</strong>ación<br />

Formalmente, una r<strong>el</strong>ación R es un conjunto <strong>de</strong> n-tuplas tal que una n-tupla<br />

cualquiera x es:<br />

{ ( , a)<br />

/ A ∈ E,<br />

a ∈ Dom(<br />

A ), ∀i,<br />

i = 1,.....<br />

n}<br />

Ai i<br />

i<br />

don<strong>de</strong> E es <strong>el</strong> esquema <strong>de</strong> la r<strong>el</strong>ación.<br />

Las propieda<strong>de</strong>s fundamentales <strong>de</strong> una r<strong>el</strong>ación son :<br />

• No hay tuplas repetidas.<br />

• Las tuplas no están or<strong>de</strong>nadas.<br />

• Los atributos no están or<strong>de</strong>nados.<br />

• Todos los valores que toman las propieda<strong>de</strong>s son atómicos.<br />

1.3.7. Grado <strong>de</strong> una r<strong>el</strong>ación<br />

El grado <strong>de</strong> una r<strong>el</strong>ación es <strong>el</strong> numero <strong>de</strong> atributos en la r<strong>el</strong>ación. Una<br />

r<strong>el</strong>ación <strong>de</strong> grado 1 (uno) es llamada unaria, una r<strong>el</strong>ación <strong>de</strong> grado 2 es llamada<br />

binaria, una r<strong>el</strong>ación <strong>de</strong> grado n es llamada <strong>de</strong> “grado n”. Los Grados <strong>de</strong> una<br />

r<strong>el</strong>ación no cambian todo <strong>el</strong> tiempo, pero es posible que se agreguen nuevas<br />

columnas y se creen nuevas r<strong>el</strong>aciones.<br />

12


1.3.8. Cardinalida<strong>de</strong>s <strong>de</strong> una r<strong>el</strong>ación.<br />

La cardinalidad <strong>de</strong> una r<strong>el</strong>ación en un <strong>de</strong>terminado momento está <strong>de</strong>finida<br />

como <strong>el</strong> número <strong>de</strong> tuplas en la r<strong>el</strong>ación. Esta pue<strong>de</strong> cambiar en cualquier<br />

momento.<br />

1.3.9. Compatibilidad <strong>de</strong> dos r<strong>el</strong>aciones.<br />

Sean A y B dos r<strong>el</strong>aciones con esquemas = { A , A ,..... A } y<br />

{ A , A ,..... A }<br />

E2 21 22 2n<br />

si :<br />

E1 11 12 1n<br />

= respectivamente. Se dice que A y B son compatibles si y sólo<br />

1. ∀ P, P ∈E1∃!<br />

P',<br />

P'∈<br />

E2<br />

tal que Dom ( P)<br />

= Dom(<br />

P')<br />

2. ∀ P, P ∈E<br />

2∃!<br />

P',<br />

P'∈<br />

E1<br />

tal que Dom ( P)<br />

= Dom(<br />

P')<br />

En la práctica, esto significa que ambas r<strong>el</strong>aciones <strong>de</strong>ben ser <strong>de</strong>l mismo<br />

grado n y que <strong>el</strong> i-esimo atributo <strong>de</strong> cada r<strong>el</strong>ación se <strong>de</strong>be basar en <strong>el</strong> mismo<br />

dominio.<br />

1.3.10. Llave Primaria / Llave Candidata<br />

La llave primaria <strong>de</strong> una r<strong>el</strong>ación o tabla es <strong>de</strong> hecho un caso especial <strong>de</strong><br />

una construcción más general llamada la llave candidata. Una llave candidata es<br />

un atributo que sirve como i<strong>de</strong>ntificador único <strong>para</strong> una <strong>de</strong>terminada tabla. Una <strong>de</strong><br />

las llaves candidatas es <strong>el</strong>egida <strong>para</strong> ser la llave primaria, las restantes pasarán a<br />

llamarse claves alternativas. De todos modos, comúnmente sólo hay una sola<br />

llave candidata. Las llaves primarias proporcionan un mecanismo <strong>de</strong><br />

direccionamiento único a niv<strong>el</strong> <strong>de</strong> tuplas <strong>para</strong> <strong>el</strong> mo<strong>de</strong>lo r<strong>el</strong>acional. Garantizan un<br />

único camino <strong>para</strong> llegar a una tupla individual y por lo tanto son fundamentales<br />

<strong>para</strong> las operaciones sobre <strong>el</strong> mo<strong>de</strong>lo r<strong>el</strong>acional.<br />

13


Formalmente, una llave se <strong>de</strong>fine como:<br />

Sea ε una r<strong>el</strong>ación con esquema E { A A , A ,...... A }<br />

1,<br />

2 3<br />

n<br />

14<br />

= . Una Llave <strong>de</strong> la<br />

r<strong>el</strong>ación ε es un atributo o un conjunto <strong>de</strong> atributos K { C , C ,..... C }<br />

= que cumple :<br />

• Unicidad: No existen dos tuplas <strong>de</strong> ε tales que <strong>para</strong> <strong>el</strong>las, <strong>el</strong> conjunto<br />

<strong>de</strong> atributos que componen K tienen los mismos valores.<br />

• Minimalidad: Ninguno <strong>de</strong> los atributos que componen K pue<strong>de</strong> ser<br />

<strong>el</strong>iminado sin afectar la unicidad.<br />

1.3.11. Llaves externas<br />

Una Llave externa se <strong>de</strong>fine como un atributo (o combinación <strong>de</strong> atributos)<br />

en una r<strong>el</strong>ación cuyos valores se requieren <strong>para</strong> emparejar a los valores <strong>de</strong> la llave<br />

primaria <strong>de</strong> otra r<strong>el</strong>ación. La llave externa y su correspondiente llave primaria<br />

<strong>de</strong>ben ser <strong>de</strong>finidas en <strong>el</strong> mismo dominio.<br />

Una llave externa no tiene que ser componente <strong>de</strong> la llave primaria <strong>de</strong> la<br />

r<strong>el</strong>ación que la contiene. El emparejamiento entre una llave externa y una llave<br />

primaria representa una referencia entre dos r<strong>el</strong>aciones, <strong>el</strong>las son <strong>el</strong> “pegamento”<br />

que mantiene la base <strong>de</strong> datos unida.<br />

1.3.12. Reglas <strong>de</strong> Integridad.<br />

Existen básicamente 2 reglas <strong>de</strong> integridad asociadas con <strong>el</strong> mo<strong>de</strong>lo<br />

r<strong>el</strong>acional, la Integridad <strong>de</strong> Entidad y la Integridad Referencial. Estas dos reglas<br />

son generales, se aplican a toda base <strong>de</strong> datos r<strong>el</strong>acional y tienen que ver con las<br />

llaves primarias y externas respectivamente. Estas reglas se refieren a los estados<br />

i<br />

j<br />

l


<strong>de</strong> la base <strong>de</strong> datos. Dado que no existe un acuerdo <strong>de</strong> como se <strong>de</strong>ben evitar los<br />

cambios <strong>de</strong> estado en la base <strong>de</strong> datos es que muchos SGBD <strong>de</strong>tienen la<br />

ejecución <strong>de</strong> la tarea en curso cada vez que se incurre en una violación a una <strong>de</strong><br />

estas reglas.<br />

La regla <strong>de</strong> Integridad <strong>de</strong> Entidad norma sobre la imposibilidad <strong>de</strong> que un<br />

atributo que componga la llave primaria <strong>de</strong> una r<strong>el</strong>ación base acepte valores nulos<br />

(NULL) 2 .<br />

La regla <strong>de</strong> integridad referencial <strong>para</strong> <strong>el</strong> mo<strong>de</strong>lo r<strong>el</strong>acional formula que si<br />

una r<strong>el</strong>ación R2 incluye una llave externa FK que empareja a una llave primaria<br />

PK <strong>de</strong> alguna r<strong>el</strong>ación R1, entonces cada valor <strong>de</strong> FK en R2 <strong>de</strong>be:<br />

a) Ser igual al valor <strong>de</strong> PK en alguna tupla <strong>de</strong> R1<br />

o<br />

b) Ser totalmente Nula, esto es, cada atributo en FK <strong>de</strong>be ser nulo.<br />

2 Un Valor nulo en <strong>el</strong> mo<strong>de</strong>lo r<strong>el</strong>acional es un valor especial distinto <strong>de</strong> cero o blanco<br />

(<strong>de</strong>pendiendo <strong>de</strong>l tipo <strong>de</strong> dato) que significa “No aplicable” o “Desconocido”. Para mayor <strong>de</strong>talle,<br />

ver la discusión sobre valores nulos en [McJones97].<br />

15


Capítulo 2. Lenguajes <strong>de</strong> consulta <strong>para</strong> <strong>el</strong> Mo<strong>de</strong>lo<br />

R<strong>el</strong>acional.<br />

2.1. Introducción.<br />

Un <strong>lenguaje</strong> <strong>de</strong> consulta es un <strong>lenguaje</strong> en <strong>el</strong> que <strong>el</strong> usuario solicita<br />

información <strong>de</strong> la base <strong>de</strong> datos, Los <strong>lenguaje</strong>s <strong>de</strong> consulta se pue<strong>de</strong>n clasificar en<br />

procedurales y no procedurales. Los <strong>lenguaje</strong>s procedurales son aqu<strong>el</strong>los en los<br />

cuales <strong>el</strong> usuario instruye al sistema <strong>para</strong> que lleve a cabo una serie <strong>de</strong><br />

operaciones en la base <strong>de</strong> datos con <strong>el</strong> fin <strong>de</strong> calcular <strong>el</strong> resultado <strong>de</strong>seado. En<br />

los <strong>lenguaje</strong>s no procedurales, en cambio, <strong>el</strong> usuario <strong>de</strong>scribe la información<br />

<strong>de</strong>seada sin dar un procedimiento concreto <strong>para</strong> obtener esta información.<br />

Los <strong>lenguaje</strong>s puros <strong>para</strong> la consulta <strong>de</strong> datos son 3. El álgebra r<strong>el</strong>acional,<br />

<strong>el</strong> cual es procedural y los cálculos r<strong>el</strong>acionales tanto <strong>de</strong> tuplas como <strong>de</strong> dominios,<br />

los cuales son <strong>lenguaje</strong>s no procedurales. Estos 3 <strong>lenguaje</strong>s son rígidos y<br />

formales, por lo tanto la mayor parte <strong>de</strong> los sistemas comerciales <strong>de</strong> bases <strong>de</strong><br />

datos r<strong>el</strong>acionales ofrecen <strong>lenguaje</strong>s <strong>de</strong> consulta mixtos, que a<strong>de</strong>más <strong>de</strong> ser ricos<br />

en sintaxis ofrecen adicionalmente sub<strong>lenguaje</strong>s <strong>de</strong> <strong>de</strong>finición <strong>de</strong> datos,<br />

administración <strong>de</strong> seguridad y otras características.<br />

Se estudiarán brevemente dos <strong>de</strong> los tres <strong>lenguaje</strong>s puros <strong>de</strong> <strong>consultas</strong> <strong>de</strong> base<br />

<strong>de</strong> datos, con <strong>el</strong> fin <strong>de</strong> presentar una base teórica <strong>para</strong> introducir SQL. Se excluirá<br />

<strong>el</strong> cálculo r<strong>el</strong>acional <strong>de</strong> dominios dado que es una generalización <strong>de</strong>l cálculo<br />

r<strong>el</strong>acional <strong>de</strong> tuplas y queda fuera <strong>de</strong>l alcance <strong>de</strong> este trabajo. Para un estudio<br />

más acabado <strong>de</strong>l cálculo r<strong>el</strong>acional <strong>de</strong> dominios se recomienda leer<br />

[Silbercshatz93].<br />

16


2.2. Algebra r<strong>el</strong>acional.<br />

El Algebra r<strong>el</strong>acional es un <strong>lenguaje</strong> <strong>de</strong> consulta procedural. Consta <strong>de</strong> un<br />

conjunto <strong>de</strong> operaciones que toman como entrada una o dos r<strong>el</strong>aciones y<br />

producen como resultado una nueva r<strong>el</strong>ación, por lo tanto, es posible anidar y<br />

combinar operadores. Hay ocho operadores en <strong>el</strong> álgebra r<strong>el</strong>acional que<br />

construyen r<strong>el</strong>aciones y manipulan datos, estos son:<br />

1. S<strong>el</strong>ección 2. Proyección 3. Producto<br />

4. Unión 5. Intersección 6. Diferencia<br />

7. JOIN 8. División<br />

Tabla 2-1 - Operadores <strong>de</strong>l Algebra r<strong>el</strong>acional<br />

Las operaciones <strong>de</strong> proyección, producto, unión, diferencia, y s<strong>el</strong>ección son<br />

llamadas primitivas, puesto que las otras tres se pue<strong>de</strong>n <strong>de</strong>finir en términos <strong>de</strong><br />

estas.<br />

Se hace necesario en este punto incluir un mo<strong>de</strong>lo <strong>de</strong> datos <strong>de</strong> ejemplo en<br />

<strong>el</strong> cual trabajar <strong>para</strong> generar ejemplos <strong>de</strong> comandos y operadores. Para este<br />

efecto se incluye un mo<strong>de</strong>lo básico <strong>de</strong> administración <strong>de</strong> RadioTaxis. El Gráfico<br />

que se presenta a continuación representa <strong>el</strong> Mo<strong>de</strong>lo conceptual (Mo<strong>de</strong>lo Lógico)<br />

o Diagrama <strong>de</strong> Entidad-R<strong>el</strong>ación:<br />

17


Vale<br />

Corr<strong>el</strong>ativo<br />

Hora <strong>de</strong>s<strong>de</strong><br />

Hora Hasta<br />

Metraje total<br />

Tarifa Total<br />

Dueño<br />

Rut<br />

Nombre<br />

T<strong>el</strong>éfono<br />

Dirección<br />

Vigencia<br />

posee es <strong>de</strong> un<br />

por genera un<br />

Movil<br />

Patente<br />

Marca<br />

Mo<strong>de</strong>lo<br />

Año<br />

realiza<br />

los hace un<br />

Viaje<br />

Hora Des<strong>de</strong><br />

Hora Hasta<br />

Origen<br />

Destino<br />

Tarifa<br />

Metraje<br />

lo maneja<br />

Figura 2-1 - Esquema <strong>de</strong> R<strong>el</strong>aciones <strong>de</strong> Ejemplo<br />

maneja<br />

Chofer<br />

Rut<br />

Nombre<br />

T<strong>el</strong>éfono<br />

Dirección<br />

Fecha_licencia_<strong>de</strong>s<strong>de</strong><br />

Fecha_licencia_hasta<br />

Vigencia<br />

Conceptual Data Mo<strong>de</strong>l<br />

Project : Control <strong>de</strong> RadioTaxis<br />

Mo<strong>de</strong>l : RadioTax<br />

Author : Mario Cisterna Version 28/12/98<br />

Los Esquemas <strong>de</strong> r<strong>el</strong>aciones que se pue<strong>de</strong>n construir a partir <strong>de</strong> este<br />

mo<strong>de</strong>lo son los siguientes:<br />

Dueño = {rut, nombre, t<strong>el</strong>éfono, dirección, vigencia}<br />

Chofer = {rut, nombre, t<strong>el</strong>éfono, dirección, fecha_licencia_<strong>de</strong>s<strong>de</strong>,<br />

fecha_licencia_hasta, vigencia}<br />

Vale = {corr<strong>el</strong>ativo, hora_<strong>de</strong>s<strong>de</strong>, hora_hasta, metraje_total,<br />

tarifa_total}<br />

Móvil = {patente, rut_dueño, rut_chofer, marca, mo<strong>de</strong>lo, año}<br />

Viaje = {corr<strong>el</strong>ativo_vale, patente_movil, Hora_Des<strong>de</strong>,<br />

hora_hasta, origen, <strong>de</strong>stino, tarifa, metraje}<br />

2.2.1. S<strong>el</strong>ección.<br />

El operador <strong>de</strong> s<strong>el</strong>ección opta por tuplas que satisfagan cierto predicado, se<br />

utiliza la letra griega sigma minúscula (σ) <strong>para</strong> señalar la s<strong>el</strong>ección. El predicado<br />

18


aparece como subíndice <strong>de</strong> σ. La R<strong>el</strong>ación que constituye <strong>el</strong> argumento se da<br />

entre paréntesis <strong>de</strong>spués <strong>de</strong> la σ.<br />

Ejemplos :<br />

2.2.2. Proyección.<br />

' ' ( ) Dueño<br />

σ vigencia = S<br />

σ<br />

patente = 'HL−8483'<br />

( Movil )<br />

La operación <strong>de</strong> proyección permite quitar ciertos atributos <strong>de</strong> la r<strong>el</strong>ación,<br />

esta operación es unaria, copiando su r<strong>el</strong>ación base dada como argumento y<br />

quitando ciertas columnas, La proyección se señala con la letra griega pi<br />

mayúscula (Π). Como subíndice <strong>de</strong> Π se coloca una lista <strong>de</strong> todos los atributos que<br />

se <strong>de</strong>sea aparezcan en <strong>el</strong> resultado. La r<strong>el</strong>ación argumento se escribe <strong>de</strong>spués <strong>de</strong><br />

Π entre paréntesis.<br />

Ejemplos :<br />

2.2.3. Producto.<br />

Π nombre,<br />

direccion ( Dueño)<br />

Π rut,<br />

vigencia ( Chofer )<br />

En álgebra r<strong>el</strong>acional <strong>el</strong> producto <strong>de</strong> dos r<strong>el</strong>aciones A y B es:<br />

A Veces B o A X B<br />

19


Produce <strong>el</strong> conjunto <strong>de</strong> todas las tuplas t tales que t es <strong>el</strong> enca<strong>de</strong>namiento <strong>de</strong> una<br />

tupla a perteneciente a A y <strong>de</strong> una b que pertenece a B. se utiliza <strong>el</strong> símbolo X<br />

<strong>para</strong> representar <strong>el</strong> producto.<br />

Ejemplos:<br />

2.2.4. Unión.<br />

Dueño × Movil<br />

Movil × Chofer<br />

En álgebra r<strong>el</strong>acional la unión <strong>de</strong> dos r<strong>el</strong>aciones compatibles 3 A y B es:<br />

A UNION B o A ∪ B<br />

Produce <strong>el</strong> conjunto <strong>de</strong> todas las tuplas que pertenecen ya sea a A o a B o a<br />

Ambas. Al igual que en teoría <strong>de</strong> conjuntos <strong>el</strong> símbolo ∪ representa aquí la unión<br />

<strong>de</strong> dos r<strong>el</strong>aciones.<br />

Ejemplo :<br />

2.2.5. Intersección.<br />

σ ∪ σ<br />

rut,<br />

vigencia(<br />

Dueño) rut,<br />

vigencia(<br />

Chofer)<br />

Devu<strong>el</strong>ve todos los Dueños y los Choferes.<br />

En álgebra r<strong>el</strong>acional la intersección <strong>de</strong> dos r<strong>el</strong>aciones compatibles A y B<br />

3 R<strong>el</strong>aciones Compatibles : En <strong>el</strong> álgebra r<strong>el</strong>acional la compatibilidad se aplica a las<br />

operaciones <strong>de</strong> Unión, Intersección y Diferencia. Cada operación requiere dos r<strong>el</strong>aciones que<br />

<strong>de</strong>ben ser compatibles, esto significa que <strong>de</strong>ben ser <strong>de</strong>l mismo grado, n, y <strong>el</strong> i-ésimo atributo <strong>de</strong><br />

cada una (i= 1, 2…n) se <strong>de</strong>be basar en <strong>el</strong> mismo dominio.<br />

20


A INTERSECCION B o A ∩ B<br />

Produce <strong>el</strong> conjunto <strong>de</strong> todas las tuplas pertenecientes a A y B. Al igual que en<br />

teoría <strong>de</strong> conjuntos <strong>el</strong> símbolo ∩ representa aquí la intersección entre dos<br />

r<strong>el</strong>aciones.<br />

Ejemplo:<br />

2.2.6. Diferencia<br />

σ ∩ σ<br />

rut,<br />

vigencia(<br />

Dueño) rut,<br />

vigencia(<br />

Chofer)<br />

Devu<strong>el</strong>ve todos los dueños que también son choferes<br />

En álgebra r<strong>el</strong>acional la diferencia entre dos r<strong>el</strong>aciones compatibles A y B<br />

A MENOS B o A – B<br />

Produce <strong>el</strong> conjunto <strong>de</strong> todas las tuplas t que pertenecen a A y no pertenecen a B.<br />

Ejemplo:<br />

2.2.7. Join o Reunión.<br />

σ − σ<br />

rut,<br />

vigencia(<br />

Dueño) rut,<br />

vigencia(<br />

Chofer)<br />

Devu<strong>el</strong>ve todos los dueños que NO son choferes<br />

En álgebra r<strong>el</strong>acional <strong>el</strong> JOIN entre <strong>el</strong> atributo X <strong>de</strong> la r<strong>el</strong>ación A con <strong>el</strong><br />

atributo Y <strong>de</strong> la r<strong>el</strong>ación B produce <strong>el</strong> conjunto <strong>de</strong> todas las tuplas t tal que t es <strong>el</strong><br />

enca<strong>de</strong>namiento <strong>de</strong> una tupla a perteneciente a A y una tupla b perteneciente a B<br />

que cumplen con <strong>el</strong> predicado “A.X comp B.Y es verda<strong>de</strong>ro” (siendo comp un<br />

21


operador r<strong>el</strong>acional y los atributos A.X y B.Y pertenecientes al mismo dominio). Si<br />

<strong>el</strong> operador r<strong>el</strong>acional “comp” es “=” entonces <strong>el</strong> conjunto resultante es un EQUI-<br />

JOIN. Si se quita uno <strong>de</strong> éstos (usando una proyección) entonces <strong>el</strong> resultado es<br />

un JOIN-NATURAL.<br />

Ejemplo :<br />

2.2.8. División<br />

σ<br />

Dueño . rut = Movil . rut _ dueño ( Dueño × Movil )<br />

En álgebra r<strong>el</strong>acional <strong>el</strong> operador <strong>de</strong> división divi<strong>de</strong> la r<strong>el</strong>ación A con grado<br />

m + n por la r<strong>el</strong>ación B entregando como resultado una r<strong>el</strong>ación con grado m. El<br />

atributo m + i <strong>de</strong> A y <strong>el</strong> atributo i <strong>de</strong> B <strong>de</strong>ben estar <strong>de</strong>finidos <strong>de</strong>ntro <strong>de</strong>l mismo<br />

dominio. Así <strong>el</strong> resultado <strong>de</strong><br />

A DIVIDIDO POR B o A / B<br />

produce la r<strong>el</strong>ación C con un sólo atributo X, tal que cada valor <strong>de</strong> x <strong>de</strong> C.X<br />

aparece como un valor <strong>de</strong> A.X, y <strong>el</strong> par <strong>de</strong> valores (x, y) aparece en A <strong>para</strong> todos<br />

los valores y que aparecen en B.<br />

Ejemplo:<br />

Π ) / Π ( σ<br />

( Chofer ) )<br />

patente , rut _ chofer ( Movil rut fecha _ licencia _ hasta<<br />

01/<br />

01/<br />

1999<br />

S<strong>el</strong>ecciona todos los autos a cuyos choferes les caduca la licencia <strong>el</strong> 01/01/1999<br />

22


2.3. Cálculo r<strong>el</strong>acional <strong>de</strong> tuplas.<br />

El cálculo r<strong>el</strong>acional <strong>de</strong> tuplas <strong>de</strong>scribe la información <strong>de</strong>seada sin dar un<br />

procedimiento específico <strong>para</strong> obtenerla. Las <strong>consultas</strong> en <strong>el</strong> cálculo r<strong>el</strong>acional <strong>de</strong><br />

tuplas se expresan como<br />

{ t | P(t)},<br />

es <strong>de</strong>cir, son <strong>el</strong> conjunto <strong>de</strong> tuplas t tales que se cumple <strong>el</strong> predicado P <strong>para</strong> cada<br />

t. Siguiendo la misma notación, se utiliza t[A] <strong>para</strong> <strong>el</strong> valor <strong>de</strong> la tupla t en <strong>el</strong><br />

atributo A.<br />

{ t | t ∈ Dueño ∧ t[<br />

vigencia]<br />

= ' S '}<br />

{ t | t ∈ Movil ∧ t[<br />

patente]<br />

= ' HL −<br />

8483'<br />

}<br />

Si sólo se <strong>de</strong>sea obtener un atributo <strong>de</strong> la tupla, se utiliza <strong>el</strong> constructor<br />

“Existe” <strong>de</strong> la lógica matemática. Así, si lo que se <strong>de</strong>sea es <strong>el</strong> Nombre <strong>de</strong> los<br />

dueños <strong>de</strong> taxis que estén vigentes:<br />

{ t | ∃ s ∈ Dueño(<br />

t[<br />

Nombre]<br />

= s[<br />

Nombre]<br />

∧ s[<br />

vigencia]<br />

= ' S ' )}<br />

"Conjunto <strong>de</strong> todas las tuplas t tales que existe una tupla s en la r<strong>el</strong>ación<br />

Dueño <strong>para</strong> la que los valores <strong>de</strong> t y <strong>de</strong> s son iguales en <strong>el</strong> atributo Nombre y <strong>el</strong><br />

valor <strong>de</strong> s <strong>para</strong> <strong>el</strong> atributo vigencia = ‘S’ ". La variable <strong>de</strong> tupla t se <strong>de</strong>fine sólo en<br />

<strong>el</strong> atributo Nombre, puesto que éste es <strong>el</strong> único atributo <strong>para</strong> <strong>el</strong> que se especifica<br />

una condición <strong>para</strong> t. Así, <strong>el</strong> resultado es una r<strong>el</strong>ación sobre (Nombre).<br />

23


Si lo que se <strong>de</strong>sea es obtener las tarifas <strong>de</strong> todos los viajes que ha<br />

efectuado todos los móviles <strong>de</strong> marca “chevrolet”, la consulta requiere <strong>de</strong> dos<br />

cláusulas “Existe” conectadas por <strong>el</strong> operador <strong>de</strong> conjunción lógica “y”.<br />

{ t | ∃s<br />

∈ Viaje(<br />

t[<br />

tarifa ] = s[<br />

tarifa ] ∧<br />

∃u<br />

∈ Movil ( s[<br />

patente]<br />

= u[<br />

patente]<br />

∧ u[<br />

marca]<br />

= " chevrolet"<br />

))}<br />

Que se lee como <strong>el</strong> conjunto <strong>de</strong> todas las tuplas(tarifa) correspondientes a los<br />

viajes que han hecho todos los móviles <strong>de</strong> marca “chevrolet”.<br />

Considérese ahora la consulta “obtener todos los RUT <strong>de</strong> los dueños <strong>de</strong><br />

móviles, cuyos móviles no hayan efectuado nunca un viaje”:<br />

{ t | ∃s<br />

∈ Movil ( t[<br />

rut ] = s[<br />

Rut ] ∧<br />

¬∃u<br />

∈ Viaje(<br />

s[<br />

patente]<br />

= u[<br />

patente]))}<br />

que ocupa la cláusula “Existe” <strong>para</strong> exigir que <strong>el</strong> dueño posea un móvil y la<br />

cláusula “no existe” <strong>para</strong> <strong>el</strong>iminar a aqu<strong>el</strong>los móviles que tengan viajes realizados.<br />

La consulta que se presenta a continuación utiliza la implicación, la fórmula “P<br />

implica Q” significa que “si P es verdad entonces Q <strong>de</strong>be ser verdad”, se introduce<br />

<strong>el</strong> constructor “<strong>para</strong> todo”. Se <strong>de</strong>sea S<strong>el</strong>ecciona todos los autos a cuyos choferes<br />

les caduca la licencia <strong>el</strong> “01/01/1999”.<br />

{ t | ∀u<br />

∈ Chofer ( u[<br />

fecha _ licencia _ hasta ] < " 01 / 01 / 1999"<br />

⇒<br />

∃s<br />

∈ Movil ( t[<br />

patente]<br />

= s[<br />

patente]<br />

∧ s[<br />

rut _ chofer ] = u[<br />

rut ])) }<br />

Que es equivalente al ejemplo dado en <strong>el</strong> punto 2.2.6 (Diferencia).<br />

24


2.3.1. Definición Formal.<br />

Una expresión <strong>de</strong>l cálculo r<strong>el</strong>acional <strong>de</strong> tuplas es <strong>de</strong> la forma:<br />

{t|P(t)} don<strong>de</strong> P es una fórmula. En una fórmula pue<strong>de</strong>n aparecer varias variables<br />

<strong>de</strong> tuplas. Se dice que una variable <strong>de</strong> tupla es una variable libre a menos que<br />

este cuantificada por un ∃ o por un ∀ que entonces se dice variable ligada.<br />

Una fórmula en <strong>el</strong> cálculo r<strong>el</strong>acional <strong>de</strong> tuplas se compone <strong>de</strong> átomos. Un<br />

átomo tiene una <strong>de</strong> las siguientes formas:<br />

1. s ∈ r, don<strong>de</strong> s es una variable <strong>de</strong> tupla y r es una r<strong>el</strong>ación. No se permite la<br />

operación ∉.<br />

2. s[x] Θ u[y], don<strong>de</strong> s y u son variables <strong>de</strong> tuplas, x e y son atributos sobre los<br />

que están <strong>de</strong>finidos s y u respectivamente, y Θ es un operador <strong>de</strong> com<strong>para</strong>ción<br />

(=). Se requiere que los atributos x e y tengan dominios cuyos<br />

miembros puedan com<strong>para</strong>rse por medio <strong>de</strong> Θ.<br />

3. s[x] Θ c, don<strong>de</strong> s es una variable <strong>de</strong> tupla, x es una atributo sobre <strong>el</strong> que s esta<br />

<strong>de</strong>finida, Θ es un operador <strong>de</strong> com<strong>para</strong>ción, y c es una constante en <strong>el</strong> dominio<br />

<strong>de</strong>l atributo x.<br />

Ahora bien, Las fórmulas se construyen a partir <strong>de</strong> átomos usando las<br />

siguientes reglas:<br />

1. Un átomo es una fórmula.<br />

2. Si P1 es una fórmula, entonces también lo son ¬P1 y (P1).<br />

25


3. Si P1 y P2 son fórmulas, entonces también lo son P1∨P2, P1∧P2 y P1⇒P2.<br />

4. Si P1(s) es una fórmula que contiene una variable <strong>de</strong> tupla libre s y r es una<br />

r<strong>el</strong>ación, entonces:<br />

también son fórmulas.<br />

∃ s ∈ r (P1(s)) y ∀ s ∈ r (P1(s))<br />

2.3.2. Seguridad <strong>de</strong> expresiones.<br />

Una expresión <strong>de</strong>l cálculo r<strong>el</strong>acional <strong>de</strong> tuplas pue<strong>de</strong> generar r<strong>el</strong>aciones<br />

infinitas. Si por ejemplo se utiliza la construcción {t | ¬(t ∈ Dueño)} hay infinitas<br />

tuplas <strong>de</strong> personas que no son dueños <strong>de</strong> algún móvil, <strong>de</strong> hecho la mayoría <strong>de</strong><br />

estas tuplas ni siquiera pertenecen a la base <strong>de</strong> datos.<br />

Para ayudar a <strong>de</strong>finir las ligaduras <strong>de</strong>l cálculo r<strong>el</strong>acional <strong>de</strong> tuplas se<br />

introduce <strong>el</strong> concepto <strong>de</strong> dominio <strong>de</strong> fórmulas. De forma intuitiva, <strong>el</strong> dominio <strong>de</strong> la<br />

fórmula P (dom(p)) es <strong>el</strong> conjunto <strong>de</strong> todos los valores a los que P hace referencia.<br />

Esto incluye a todos los valores mencionados en P como todos los valores que<br />

aparezcan en las r<strong>el</strong>aciones referenciadas por P.<br />

Se dice que una expresión {t | P(t)} es segura si todos los valores que<br />

aparecen en <strong>el</strong> resultado son valores <strong>de</strong>l dominio <strong>de</strong> P.<br />

2.3.3. Potencia expresiva <strong>de</strong> los <strong>lenguaje</strong>s.<br />

El cálculo r<strong>el</strong>acional <strong>de</strong> tuplas restringido a expresiones seguras es<br />

equivalente en potencia expresiva al álgebra r<strong>el</strong>acional. Por lo tanto, <strong>para</strong> cada<br />

expresión <strong>de</strong>l álgebra r<strong>el</strong>acional hay una expresión equivalente en <strong>el</strong> cálculo<br />

r<strong>el</strong>acional <strong>de</strong> tuplas y viceversa. La <strong>de</strong>mostración <strong>de</strong> este hecho queda fuera <strong>de</strong><br />

los alcances <strong>de</strong> este trabajo, una prueba formal <strong>de</strong> la equivalencia entre <strong>el</strong> cálculo<br />

26


<strong>el</strong>acional <strong>de</strong> tuplas y <strong>el</strong> álgebra r<strong>el</strong>acional propuesta por E.F. Codd se pue<strong>de</strong><br />

encontrar en [Codd71].<br />

2.4. SQL como <strong>lenguaje</strong> <strong>de</strong> <strong>consultas</strong> r<strong>el</strong>acionales.<br />

2.4.1. Introducción.<br />

Los <strong>lenguaje</strong>s formales presentados en las secciones 2.2 y 2.3<br />

proporcionan una notación concisa <strong>para</strong> la representación <strong>de</strong> <strong>consultas</strong>. Sin<br />

embargo, los sistemas <strong>de</strong> base <strong>de</strong> datos necesitan un <strong>lenguaje</strong> <strong>de</strong> <strong>consultas</strong> más<br />

cómodo <strong>para</strong> <strong>el</strong> usuario. Aunque SQL se consi<strong>de</strong>re un <strong>lenguaje</strong> <strong>de</strong> <strong>consultas</strong>,<br />

contiene muchas otras capacida<strong>de</strong>s que incluyen características <strong>para</strong> <strong>de</strong>finir<br />

estructuras <strong>de</strong> datos, modificación <strong>de</strong> datos y la especificación <strong>de</strong> restricciones <strong>de</strong><br />

integridad.<br />

SQL se ha establecido como <strong>el</strong> <strong>lenguaje</strong> estándar <strong>de</strong> base <strong>de</strong> datos<br />

r<strong>el</strong>acionales. Hay numerosas versiones <strong>de</strong> SQL. La versión original se <strong>de</strong>sarrollo<br />

en <strong>el</strong> laboratorio <strong>de</strong> investigación <strong>de</strong> San Jose, California (San Jose Research<br />

Center) <strong>de</strong> IBM, este <strong>lenguaje</strong> originalmente <strong>de</strong>nominado Sequ<strong>el</strong>, se implementó<br />

como parte <strong>de</strong>l proyecto System R, a principios <strong>de</strong> 1970 [McJones97]. Des<strong>de</strong><br />

entonces ha evolucionado a lo que ahora se conoce como SQL (Structured Query<br />

Language, o <strong>lenguaje</strong> estructurado <strong>de</strong> <strong>consultas</strong>).<br />

En 1986, ANSI (American National Standards Institute, Instituto Nacional<br />

Americano <strong>de</strong> Normalización) e ISO (International Standards Organization,<br />

Organización Internacional <strong>de</strong> Normalización) Publicaron una norma <strong>de</strong> SQL<br />

<strong>de</strong>nominada SQL-86. En 1987 IBM publicó su propia norma <strong>de</strong> SQL <strong>de</strong>nominada<br />

SAA-SQL(System Application Architecture Database Interfaz, Interfaz <strong>de</strong> base <strong>de</strong><br />

datos <strong>para</strong> arquitecturas <strong>de</strong> aplicación <strong>de</strong> sistemas). En 1989 se publicó una<br />

27


norma extendida <strong>para</strong> SQL (SQL-89) y actualmente los SGBD son compatibles al<br />

menos con esta norma. La norma actual <strong>de</strong> SQL <strong>de</strong> ANSI/ISO es la SQL-92. Se<br />

<strong>de</strong>be tener en cuenta que algunas implementaciones <strong>de</strong> SQL pue<strong>de</strong>n ser<br />

compatibles sólo con SQL-89, no siéndolo con SQL-92.<br />

SQL proporciona dos tipos <strong>de</strong> <strong>lenguaje</strong>s diferentes: uno <strong>para</strong> especificar <strong>el</strong><br />

esquema r<strong>el</strong>acional y <strong>el</strong> otro <strong>para</strong> expresar las <strong>consultas</strong> y actualizaciones <strong>de</strong> la<br />

base <strong>de</strong> datos.<br />

2.4.2. Lenguaje <strong>de</strong> <strong>de</strong>finición <strong>de</strong> datos (DDL – Data Definition<br />

Language)<br />

Un esquema <strong>de</strong> bases <strong>de</strong> datos se representa mediante un sub<strong>lenguaje</strong><br />

especial llamado <strong>lenguaje</strong> <strong>de</strong> <strong>de</strong>finición <strong>de</strong> datos. El resultado <strong>de</strong> la compilación <strong>de</strong><br />

estas instrucciones es un conjunto <strong>de</strong> tablas, r<strong>el</strong>aciones y reglas cuyas<br />

<strong>de</strong>finiciones quedan almacenadas en un archivo (tabla u otro medio <strong>de</strong><br />

almacenamiento) que contiene “metadatos”, esto es, datos acerca <strong>de</strong> datos. Este<br />

archivo comúnmente llamado diccionario <strong>de</strong> datos (o catalogo <strong>de</strong>l sistema) es <strong>el</strong><br />

que se consulta toda vez que se quiere leer, modificar o <strong>el</strong>iminar los datos <strong>de</strong> la<br />

base <strong>de</strong> datos.<br />

28


2.4.3. Lenguaje <strong>de</strong> manipulación <strong>de</strong> datos (DML – Data Manipulation<br />

Language)<br />

Un D.M.L. es un sub<strong>lenguaje</strong> <strong>de</strong> consulta y manipulación <strong>de</strong> datos.<br />

Se enten<strong>de</strong>rá por manipulación <strong>de</strong> datos la :<br />

• Recuperación <strong>de</strong> Información.<br />

• Inserción <strong>de</strong> nueva Información.<br />

• Eliminación (Borrado) <strong>de</strong> información existente.<br />

• Modificación <strong>de</strong> Información Almacenada.<br />

2.4.4. Otras características <strong>de</strong> SQL.<br />

A<strong>de</strong>más <strong>de</strong> los dos tipos <strong>de</strong> sub<strong>lenguaje</strong>s mencionados anteriormente, SQL<br />

pue<strong>de</strong> ser utilizado <strong>para</strong> otras características propias que no poseen los <strong>lenguaje</strong>s<br />

formales <strong>de</strong> <strong>consultas</strong>, estas son:<br />

• Definición <strong>de</strong> vistas. El DDL <strong>de</strong> SQL incluye instrucciones <strong>para</strong> la<br />

<strong>de</strong>finición <strong>de</strong> vistas.<br />

• Autorización. El DDL <strong>de</strong> SQL incluye instrucciones <strong>para</strong> la<br />

especificación <strong>de</strong> los <strong>de</strong>rechos <strong>de</strong> acceso a los objetos <strong>de</strong> la base <strong>de</strong><br />

datos.<br />

• Integridad. El DDL <strong>de</strong> SQL también incluye un conjunto <strong>de</strong> sentencias<br />

<strong>para</strong> la especificación <strong>de</strong> restricciones <strong>de</strong> integridad.<br />

• Control <strong>de</strong> transacciones. SQL incluye or<strong>de</strong>nes <strong>para</strong> la especificación<br />

<strong>de</strong> los estados <strong>de</strong> una transacción, algunas implementaciones permiten<br />

29


a<strong>de</strong>más <strong>el</strong> bloqueo explicito <strong>de</strong> objetos <strong>de</strong> datos con <strong>el</strong> fin <strong>de</strong> manejar<br />

control <strong>de</strong> concurrencia.<br />

Para los efectos <strong>de</strong> este trabajo se anexa en <strong>el</strong> apéndice A una breve<br />

<strong>de</strong>scripción <strong>de</strong> los sub<strong>lenguaje</strong>s <strong>de</strong> Definición y manipulación <strong>de</strong> datos.<br />

30


Capítulo 3. Sistemas <strong>de</strong> Gestión <strong>de</strong> Bases <strong>de</strong> datos<br />

R<strong>el</strong>acionales.<br />

3.1. Introducción.<br />

Un Sistema <strong>de</strong> Gestión <strong>de</strong> Bases <strong>de</strong> datos (SGBD) consiste en una<br />

colección <strong>de</strong> datos interr<strong>el</strong>acionados y una colección <strong>de</strong> programas <strong>para</strong> acce<strong>de</strong>r a<br />

esos datos. El objetivo principal <strong>de</strong> un SGBD es proporcionar un entorno que sea<br />

tanto conveniente como eficiente <strong>para</strong> las personas que lo ocupan en <strong>el</strong><br />

almacenamiento y recuperación <strong>de</strong> la información.<br />

Los sistemas <strong>de</strong> bases <strong>de</strong> datos se diseñan <strong>para</strong> almacenar gran<strong>de</strong>s<br />

volúmenes <strong>de</strong> información, la gestión <strong>de</strong> los datos implica entonces la <strong>de</strong>finición<br />

<strong>de</strong> estructuras <strong>para</strong> <strong>el</strong> almacenamiento <strong>de</strong> la información y la provisión <strong>de</strong><br />

mecanismos <strong>para</strong> la manipulación <strong>de</strong> estos. A<strong>de</strong>más <strong>de</strong>ben proporcionar<br />

mecanismos <strong>de</strong> seguridad <strong>de</strong> los datos que protejan al sistema frente a caídas o a<br />

intentos <strong>de</strong> acceso <strong>de</strong> personas no autorizadas. Si los datos están compartidos<br />

por varios usuarios, <strong>el</strong> sistema <strong>de</strong>be asegurar la consistencia <strong>de</strong> los datos evitando<br />

posibles resultados anómalos.<br />

Un propósito principal <strong>de</strong> un sistema <strong>de</strong> bases <strong>de</strong> datos es proporcionar a<br />

los usuarios una visión abstracta <strong>de</strong> los datos. Esto se logra mediante la <strong>de</strong>finición<br />

<strong>de</strong> 3 niv<strong>el</strong>es <strong>de</strong> abstracción que pue<strong>de</strong>n ser observados: <strong>el</strong> niv<strong>el</strong> físico, <strong>el</strong> niv<strong>el</strong><br />

lógico y <strong>el</strong> niv<strong>el</strong> <strong>de</strong> vistas.<br />

El niv<strong>el</strong> físico es <strong>el</strong> niv<strong>el</strong> más bajo <strong>de</strong> abstracción, es <strong>el</strong> que <strong>de</strong>scribe como<br />

se almacenan los datos, a su vez, <strong>el</strong> niv<strong>el</strong> lógico <strong>de</strong>scribe que datos se<br />

almacenan realmente en la base <strong>de</strong> datos y que r<strong>el</strong>aciones existen entre estos<br />

31


datos. El niv<strong>el</strong> más alto <strong>de</strong> abstracción <strong>de</strong> datos es <strong>el</strong> niv<strong>el</strong> <strong>de</strong> vistas, <strong>el</strong> cual sólo<br />

presenta una <strong>de</strong>terminada porción <strong>de</strong> la base <strong>de</strong> datos, <strong>de</strong>pendiendo <strong>de</strong>l tipo <strong>de</strong><br />

usuario que la consulta, así, <strong>el</strong> sistema pue<strong>de</strong> proporcionar muchas vistas <strong>para</strong> la<br />

base <strong>de</strong> datos.<br />

Una base <strong>de</strong> datos sufre constantes cambios en <strong>el</strong> contenido <strong>de</strong> la<br />

información que contiene en <strong>el</strong> transcurso <strong>de</strong>l tiempo. La colección <strong>de</strong> datos<br />

almacenada en un momento particular se <strong>de</strong>nomina ejemplar <strong>de</strong> la base <strong>de</strong> datos.<br />

El diseño completo <strong>de</strong> la base <strong>de</strong> datos se llama esquema <strong>de</strong> la base <strong>de</strong> datos.<br />

La capacidad <strong>de</strong> modificar la <strong>de</strong>finición <strong>de</strong>l esquema en un niv<strong>el</strong> sin que<br />

afecte a una <strong>de</strong>finición <strong>de</strong> esquema en <strong>el</strong> niv<strong>el</strong> inmediatamente superior se<br />

<strong>de</strong>nomina in<strong>de</strong>pen<strong>de</strong>ncia <strong>de</strong> datos. Existen 2 niv<strong>el</strong>es <strong>de</strong> in<strong>de</strong>pen<strong>de</strong>ncia <strong>de</strong> datos:<br />

La in<strong>de</strong>pen<strong>de</strong>ncia física <strong>de</strong> datos y la in<strong>de</strong>pen<strong>de</strong>ncia lógica.<br />

La In<strong>de</strong>pen<strong>de</strong>ncia física <strong>de</strong> los datos se <strong>de</strong>scribe como la capacidad <strong>de</strong><br />

modificar <strong>el</strong> niv<strong>el</strong> físico <strong>de</strong> la base <strong>de</strong> datos sin tener que rescribir los programas<br />

<strong>de</strong> aplicación. En tanto la in<strong>de</strong>pen<strong>de</strong>ncia lógica se <strong>de</strong>fine como la capacidad <strong>de</strong><br />

modificar <strong>el</strong> esquema lógico sin causar que los programas <strong>de</strong> aplicación tengan<br />

que rescribirse.<br />

Un esquema <strong>de</strong> base <strong>de</strong> datos se especifica mediante un conjunto <strong>de</strong><br />

<strong>de</strong>finiciones expresadas en un DDL (Lenguaje <strong>de</strong> <strong>de</strong>finición <strong>de</strong> datos). El resultado<br />

<strong>de</strong> esta <strong>de</strong>finición es un conjunto <strong>de</strong> tablas y r<strong>el</strong>aciones que se almacenan en una<br />

tabla (o un conjunto <strong>de</strong> tablas) especial que se i<strong>de</strong>ntifica como <strong>el</strong> diccionario <strong>de</strong><br />

datos o <strong>el</strong> catálogo <strong>de</strong> la base <strong>de</strong> datos.<br />

Una transacción <strong>de</strong> base <strong>de</strong> datos se <strong>de</strong>fine como colección <strong>de</strong> operaciones<br />

que se lleva a cabo como una función lógica simple en una aplicación <strong>de</strong> base <strong>de</strong><br />

datos. Cada transacción es una unidad <strong>de</strong> atomicidad y consistencia. La<br />

32


atomicidad aquí se entien<strong>de</strong> como la capacidad <strong>de</strong> que muchas instrucciones se<br />

entiendan en ciertos casos como una sola, la consistencia se refiere a la<br />

capacidad <strong>de</strong> respetar las restricciones <strong>de</strong> consistencia <strong>de</strong> datos que posee la<br />

base <strong>de</strong> datos antes y <strong>de</strong>spués <strong>de</strong> ejecutar una transacción. El gestor <strong>de</strong><br />

transacciones es <strong>el</strong> responsable <strong>de</strong> asegurar que la base <strong>de</strong> datos permanezca en<br />

un estado consistente a pesar <strong>de</strong> los fallos <strong>de</strong>l sistema. El gestor <strong>de</strong> transacciones<br />

también asegura que la ejecución <strong>de</strong> transacciones concurrentes ocurran sin<br />

conflictos. El gestor <strong>de</strong> almacenamiento <strong>de</strong> la base <strong>de</strong> datos es un programa (o<br />

modulo) que proporciona la interfaz entre los datos <strong>de</strong> bajo niv<strong>el</strong> almacenados en<br />

la base <strong>de</strong> datos y los programas <strong>de</strong> aplicación y las <strong>consultas</strong> enviadas al<br />

sistema. El gestor <strong>de</strong> almacenamiento es <strong>el</strong> responsable <strong>de</strong> la interacción con los<br />

datos almacenados en disco.<br />

3.2. Transacciones, concurrencia y recuperación.<br />

3.2.1. Transacciones.<br />

Una transacción es una unidad <strong>de</strong> la ejecución <strong>de</strong> un programa que acce<strong>de</strong><br />

y posiblemente actualiza varios <strong>el</strong>ementos <strong>de</strong> datos. Se <strong>de</strong>limita <strong>de</strong>pendiendo <strong>de</strong>l<br />

<strong>lenguaje</strong> por las sentencias inicio transacción y fin transacción y se compone <strong>de</strong><br />

todas las instrucciones que se encuentran entre estos dos <strong>de</strong>limitadores.<br />

Para asegurar la consistencia <strong>de</strong> los datos se necesita que <strong>el</strong> sistema <strong>de</strong><br />

base <strong>de</strong> datos tengan las propieda<strong>de</strong>s llamadas ACID: (Atomicity, Consistency,<br />

Isolation, Durability - Atomicidad, Consistencia, Aislamiento, Durabilidad<br />

[Silberschatz97].<br />

La atomicidad asegura que o bien todos los efectos <strong>de</strong> la transacción se<br />

reflejan en la base <strong>de</strong> datos, o bien ninguno <strong>de</strong> <strong>el</strong>los; un fallo no pue<strong>de</strong> <strong>de</strong>jar a la<br />

base <strong>de</strong> datos en un estado en <strong>el</strong> cual una transacción se haya ejecutado<br />

33


parcialmente. La consistencia asegura que si la base <strong>de</strong> datos es consistente<br />

inicialmente, la ejecución <strong>de</strong> la transacción <strong>de</strong>ja la base <strong>de</strong> datos en un estado<br />

consistente. El aislamiento asegura que en la ejecución concurrente <strong>de</strong><br />

transacciones, estas están aisladas unas <strong>de</strong> otras, <strong>de</strong> tal manera que cada una<br />

tiene la impresión <strong>de</strong> que ninguna otra transacción se ejecuta concurrentemente<br />

con <strong>el</strong>la. La durabilidad asegura que una vez que la transacción se ha<br />

comprometido, las actualizaciones hechas por la transacción no se pier<strong>de</strong>n,<br />

incluso si hay un fallo en <strong>el</strong> sistema.<br />

Una transacción que termina con éxito se dice que está comprometida<br />

(commited), una transacción que haya sido comprometida llevará a la base <strong>de</strong><br />

datos a un nuevo estado consistente que <strong>de</strong>be permanecer incluso si hay un fallo<br />

en <strong>el</strong> sistema. En cualquier momento una transacción sólo pue<strong>de</strong> estar en uno <strong>de</strong><br />

los siguientes estados.<br />

• Activa (Active): <strong>el</strong> estado inicial; la transacción permanece en este estado<br />

durante su ejecución.<br />

• Parcialmente comprometida (Uncommited): Después <strong>de</strong> ejecutarse la ultima<br />

transacción.<br />

• Fallida (Failed): tras <strong>de</strong>scubrir que no se pue<strong>de</strong> continuar la ejecución normal.<br />

• Abortada (Rolled Back): <strong>de</strong>spués <strong>de</strong> haber retrocedido la transacción y<br />

restablecido la base <strong>de</strong> datos a su estado anterior al comienzo <strong>de</strong> la<br />

transacción.<br />

• Comprometida (Commited): tras completarse con éxito.<br />

Cuando varias transacciones se ejecutan concurrentemente, existe la<br />

posibilidad <strong>de</strong> que se pierda la consistencia <strong>de</strong> datos. Se hace necesario por lo<br />

tanto un sistema que controle la interacción entre las transacciones concurrentes.<br />

Puesto que una transacción por <strong>de</strong>finición conserva la consistencia, una ejecución<br />

34


lineal <strong>de</strong> transacciones la garantiza también. Un sistema que asegure esta<br />

propiedad se dice que asegura la secuencialidad.<br />

3.2.2. Concurrencia.<br />

Existen varios esquemas <strong>de</strong> control <strong>de</strong> concurrencia que aseguran la<br />

secuencialidad, todos estos esquemas o bien retrasan una operación o bien<br />

abortan la transacción que ha realizado la operación. Los más conocidos son los<br />

protocolos <strong>de</strong> bloqueo, <strong>el</strong> esquema <strong>de</strong> or<strong>de</strong>nación por marcas temporales, las<br />

técnicas <strong>de</strong> validación, <strong>el</strong> esquema <strong>de</strong> granularidad múltiple y los esquemas<br />

multiversión.<br />

Un protocolo <strong>de</strong> bloqueo es un conjunto <strong>de</strong> reglas que indican <strong>el</strong> momento<br />

en que una transacción pue<strong>de</strong> bloquear o <strong>de</strong>sbloquear un objeto <strong>de</strong> la base <strong>de</strong><br />

datos. El protocolo <strong>de</strong> bloqueo <strong>de</strong> dos fases permite que una transacción bloquee<br />

un objeto sólo <strong>de</strong>spués <strong>de</strong> que haya <strong>de</strong>sbloqueado otro objeto distinto, este<br />

método asegura la secuencialidad.<br />

El esquema <strong>de</strong> or<strong>de</strong>nación por marcas temporales asegura la<br />

secuencialidad s<strong>el</strong>eccionando previamente un or<strong>de</strong>n en todo par <strong>de</strong> transacciones.<br />

Existen 2 formas <strong>de</strong> implementar este esquema, uno es por medio <strong>de</strong> valores<br />

timestamp (<strong>de</strong>pendientes <strong>de</strong>l r<strong>el</strong>oj <strong>de</strong>l sistema) y por medio <strong>de</strong> un contador lógico<br />

que se incrementa cada vez que asigna una nueva marca temporal. Este<br />

protocolo asegura la secuencialidad en cuanto a conflictos y la ausencia <strong>de</strong><br />

interbloqueos, si una <strong>de</strong> las transacciones viola la norma la transacción se retrasa<br />

y se le asigna una nueva marca temporal. Por ejemplo, una operación leer se<br />

pue<strong>de</strong> retrasar porque todavía no se ha escrito <strong>el</strong> valor apropiado o incluso<br />

rechazar si ha sobrescrito <strong>el</strong> valor que supuestamente se iba a leer.<br />

35


Un esquema <strong>de</strong> validación es un método <strong>de</strong> control <strong>de</strong> concurrencia<br />

a<strong>de</strong>cuado <strong>para</strong> transacciones <strong>de</strong> sólo lectura y en las cuales la tasa <strong>de</strong> conflictos<br />

es baja. Se basa en dividir una transacción en 3 etapas (lectura, validación y<br />

escritura) y trabajar con <strong>el</strong> esquema <strong>de</strong> marcas temporales sobre la etapa <strong>de</strong><br />

validación. De esta manera se quita una sobrecarga en la etapa <strong>de</strong> lectura, en la<br />

cual no se necesita un esquema <strong>de</strong> control <strong>de</strong> concurrencia dado que toda lectura<br />

lleva a la base <strong>de</strong> datos al mismo estado <strong>de</strong> consistencia.<br />

Una manera distinta manejar la concurrencia es por medio <strong>de</strong> la<br />

granularidad, este concepto permite agrupar varios <strong>el</strong>ementos <strong>de</strong> datos y <strong>de</strong>finirlos<br />

como un todo <strong>para</strong> efectos <strong>de</strong> sincronización. Se <strong>de</strong>fine como una jerarquía <strong>de</strong><br />

distintos niv<strong>el</strong>es, don<strong>de</strong> <strong>el</strong> niv<strong>el</strong> superior pue<strong>de</strong> representar toda la base <strong>de</strong> datos,<br />

se esquematiza como estructura <strong>de</strong> árbol don<strong>de</strong> los nodos hijos <strong>de</strong> un nodo<br />

interno representan las <strong>de</strong>pen<strong>de</strong>ncias <strong>de</strong> datos asociadas. Se utilizan los tipos <strong>de</strong><br />

bloqueos Compartidos y Exclusivos más un nuevo tipo <strong>de</strong> bloqueo llamado <strong>el</strong><br />

bloqueo intencional, <strong>el</strong> cual indica que existen nodos <strong>de</strong>scendientes que tienen<br />

bloqueos compartidos o exclusivos.<br />

El esquema multiversión se basa en la creación <strong>de</strong> nuevas versiones <strong>de</strong> los<br />

<strong>el</strong>ementos <strong>de</strong> datos cada vez que una transacción vaya a escribir dicho <strong>el</strong>emento.<br />

Cuando se va a realizar una escritura <strong>el</strong> sistema <strong>el</strong>ige una <strong>de</strong> las versiones <strong>para</strong><br />

que se lea. El esquema <strong>de</strong> control <strong>de</strong> versiones garantiza que la versión que se va<br />

a leer se <strong>el</strong>ige <strong>de</strong> forma que asegure la secuencialidad por medio <strong>de</strong> marcas<br />

temporales. En este esquema una operación <strong>de</strong> lectura tiene éxito siempre, sin<br />

embargo, una operación <strong>de</strong> escritura pue<strong>de</strong> provocar <strong>el</strong> retroceso <strong>de</strong> una<br />

transacción.<br />

Un sistema está en estado <strong>de</strong> interbloqueo si existe un conjunto <strong>de</strong><br />

transacciones tal que toda transacción <strong>de</strong>l conjunto está esperando a otra<br />

transacción <strong>de</strong>l conjunto. En tal situación, ninguna <strong>de</strong> las transacciones pue<strong>de</strong><br />

36


progresar. Existen 2 métodos <strong>para</strong> tratar los interbloqueos y ambos provocan un<br />

retroceso <strong>de</strong> las transacciones, la diferencia radica en que uno es preventivo y otro<br />

curativo. El protocolo <strong>de</strong> prevención <strong>de</strong> interbloqueos asegura que <strong>el</strong> sistema<br />

nunca llegará a un estado <strong>de</strong> interbloqueos mientras que <strong>el</strong> método <strong>de</strong> <strong>de</strong>tección y<br />

recuperación <strong>de</strong> interbloqueos permite que <strong>el</strong> sistema llegue a un estado <strong>de</strong><br />

interbloqueos <strong>para</strong> luego tratar <strong>de</strong> recuperarse. La prevención se usa normalmente<br />

cuando la probabilidad <strong>de</strong> que <strong>el</strong> sistema llegue a un estado <strong>de</strong> interbloqueo es<br />

r<strong>el</strong>ativamente alta, <strong>de</strong> lo contrario lo más conveniente es usar la <strong>de</strong>tección y<br />

recuperación.<br />

3.2.3. Recuperación.<br />

Los fallos que ocurren en un computador pue<strong>de</strong>n darse por diferentes<br />

motivos (fallos <strong>de</strong> disco, cortes <strong>de</strong> energía o fallos en <strong>el</strong> software). En cada uno <strong>de</strong><br />

estos casos pue<strong>de</strong> per<strong>de</strong>rse información concerniente a la base <strong>de</strong> datos. Existen<br />

varios tipos <strong>de</strong> fallas, a consi<strong>de</strong>rar:<br />

• Fallo en la transacción, que a su vez se divi<strong>de</strong>n en errores lógicos y errores <strong>de</strong>l<br />

sistema. Un error lógico ocurre cuando una transacción no pue<strong>de</strong> continuar con<br />

su ejecución normal a causa <strong>de</strong> una condición interna como lo es un<br />

<strong>de</strong>sbordamiento o un exceso <strong>de</strong> recursos. Un error <strong>de</strong>l sistema ocurre cuando<br />

<strong>el</strong> sistema se encuentra en un estado no <strong>de</strong>seado como en <strong>el</strong> caso <strong>de</strong> los<br />

interbloqueos.<br />

• Caída <strong>de</strong>l sistema, provocado ya sea por <strong>el</strong> hardware, <strong>el</strong> sistema operativo o<br />

por <strong>el</strong> software <strong>de</strong> base <strong>de</strong> datos. Comúnmente causa la pérdida <strong>de</strong>l contenido<br />

<strong>de</strong> la memoria primaria y aborta <strong>el</strong> procesamiento <strong>de</strong> una transacción.<br />

37


• Fallo <strong>de</strong> disco, <strong>para</strong> <strong>el</strong> cual sólo sirve la recuperación por medio <strong>de</strong> copias<br />

existentes en medios <strong>de</strong> almacenamiento secundario como cintas magnéticas.<br />

La forma más aceptada <strong>de</strong> lograr un tipo <strong>de</strong> almacenamiento lo más estable<br />

posible es replicando la información en varios medios <strong>de</strong> almacenamiento no<br />

volátil, con modos <strong>de</strong> fallos in<strong>de</strong>pendientes. Los sistemas RAID (disposición<br />

redundante <strong>de</strong> discos in<strong>de</strong>pendientes) garantizan que <strong>el</strong> fallo <strong>de</strong> un sólo disco no<br />

conduzca a la perdida <strong>de</strong> datos. Sin embargo los sistemas RAID, no pue<strong>de</strong>n<br />

proteger al sistema <strong>de</strong> una pérdida <strong>de</strong> datos en <strong>el</strong> caso <strong>de</strong> una catástrofe<br />

geográfica, <strong>para</strong> tales efectos muchos sistemas <strong>de</strong> almacenamiento guardan<br />

copias <strong>de</strong> seguridad en cintas en otros lugares, no obstante, como las cintas no<br />

pue<strong>de</strong>n ser trasladadas continuamente, los últimos cambios realizados luego <strong>de</strong>l<br />

traslado <strong>de</strong> cintas no se pue<strong>de</strong>n volver a recuperar en <strong>el</strong> caso <strong>de</strong> tales <strong>de</strong>sastres.<br />

Los sistemas más seguros guardan copias <strong>de</strong> cada bloque <strong>de</strong> almacenamiento en<br />

otra disposición geográfica, datos que se transmiten por medios <strong>de</strong> re<strong>de</strong>s <strong>de</strong><br />

computadores al sistema <strong>de</strong> respaldo remoto.<br />

El estado <strong>de</strong> un sistema <strong>de</strong> base <strong>de</strong> datos pue<strong>de</strong> no volver a ser consistente<br />

en caso <strong>de</strong> que ocurran fallos, <strong>para</strong> preservar la consistencia es necesario que<br />

cada transacción sea atómica. Garantizar la propiedad <strong>de</strong> atomicidad es<br />

responsabilidad <strong>de</strong>l esquema <strong>de</strong> recuperación.<br />

Existen básicamente 2 esquemas que garantizan la atomicidad.<br />

Basados en <strong>el</strong> registro histórico 4 . Todas las modificaciones se graban en <strong>el</strong><br />

registro histórico, <strong>el</strong> cual <strong>de</strong>be estar guardado en almacenamiento estable. En <strong>el</strong><br />

esquema <strong>de</strong> modificación diferida, durante la ejecución <strong>de</strong> una transacción, se<br />

difieren todas las operaciones <strong>de</strong> escritura hasta que la transacción se<br />

4 Comúnmente llamado log <strong>de</strong> transacciones.<br />

38


compromete parcialmente, momento en <strong>el</strong> cual se utiliza la información <strong>de</strong>l registro<br />

histórico asociado con la transacción <strong>para</strong> ejecutar las escrituras diferidas. Con la<br />

técnica <strong>de</strong> modificación inmediata todas las modificaciones se aplican<br />

directamente en la base <strong>de</strong> datos. Si ocurre una caída se utiliza la información <strong>de</strong>l<br />

registro histórico <strong>para</strong> llevar a la base <strong>de</strong> datos a un estado estable previo.<br />

Paginación en la sombra. Durante la vida <strong>de</strong> una transacción se mantienen<br />

2 tablas <strong>de</strong> páginas: la tabla actual <strong>de</strong> páginas y la tabla <strong>de</strong> páginas sombra.<br />

Ambas tablas son idénticas al principio <strong>de</strong> la transacción, sin embargo, la tabla<br />

actual <strong>de</strong> páginas pue<strong>de</strong> ir cambiando luego <strong>de</strong> cada operación escribir. Todas las<br />

operaciones <strong>de</strong> lectura y escritura utilizan la tabla <strong>de</strong> páginas actual, cuando una<br />

transacción se compromete parcialmente se <strong>de</strong>secha la tabla <strong>de</strong> páginas sombra y<br />

la tabla actual se convierte en la nueva tabla <strong>de</strong> páginas. Si la transacción fracasa,<br />

simplemente se <strong>de</strong>secha la tabla actual <strong>de</strong> páginas.<br />

El procesamiento <strong>de</strong> transacciones se basa en un mo<strong>de</strong>lo <strong>de</strong><br />

almacenamiento en <strong>el</strong> cual la memoria principal contiene una memoria intermedia<br />

<strong>para</strong> <strong>el</strong> registro histórico, una memoria intermedia <strong>para</strong> la base <strong>de</strong> datos y una<br />

memoria intermedia <strong>para</strong> <strong>el</strong> sistema. Una implementación eficiente <strong>de</strong> un<br />

esquema <strong>de</strong> recuperación <strong>de</strong> datos requiere que sea mínimo <strong>el</strong> número <strong>de</strong><br />

escrituras <strong>de</strong> la base <strong>de</strong> datos y que sea realizado en almacenamiento estable.<br />

Los registros <strong>de</strong>l registro histórico pue<strong>de</strong>n guardarse inicialmente en la memoria<br />

intermedia <strong>de</strong>l registro histórico pero <strong>de</strong>ben ser llevados a almacenamiento estable<br />

bajo dos situaciones:<br />

a) <strong>de</strong>ben escribirse en almacenamiento estable todos los registros <strong>de</strong>l registro<br />

histórico que referencien a la transacción Ti antes <strong>de</strong> grabar <strong>el</strong> registro que<br />

indique que la transacción Ti ha sido comprometida<br />

39


) <strong>de</strong>ben escribirse en almacenamiento estable todos los registros <strong>de</strong>l registro<br />

histórico pertenecientes a los datos <strong>de</strong> un bloque antes <strong>de</strong> que ese bloque <strong>de</strong><br />

datos se escriba <strong>de</strong>s<strong>de</strong> la memoria intermedia a la base <strong>de</strong> datos.<br />

3.3. Tipos <strong>de</strong> SGBD.<br />

La arquitectura <strong>de</strong> un sistema <strong>de</strong> base <strong>de</strong> datos está influenciada por <strong>el</strong><br />

sistema informático que soporta la instalación <strong>de</strong>l SGBD, lo que reflejará muchas<br />

<strong>de</strong> las características propias <strong>de</strong>l sistema subyacente en <strong>el</strong> SGBD.<br />

La re<strong>de</strong>s <strong>de</strong> computadores permiten se<strong>para</strong>r tareas en un esquema <strong>de</strong><br />

clientes y servidores, <strong>el</strong> procesamiento <strong>para</strong>l<strong>el</strong>o <strong>de</strong>ntro <strong>de</strong>l computador permite<br />

ac<strong>el</strong>erar algunas <strong>de</strong> las tareas <strong>de</strong> la base <strong>de</strong> datos así como la posibilidad <strong>de</strong><br />

ejecutar más transacciones por segundo. Las <strong>consultas</strong> se pue<strong>de</strong>n <strong>para</strong>l<strong>el</strong>izar<br />

permitiendo así que una consulta se pueda ejecutar por más <strong>de</strong> un procesador al<br />

mismo tiempo, esta característica ha llevado al estudio <strong>de</strong> las bases <strong>de</strong> datos<br />

<strong>para</strong>l<strong>el</strong>as.<br />

La distribución <strong>de</strong> datos a través <strong>de</strong> distintos <strong>de</strong>partamentos <strong>de</strong> una<br />

organización permite que <strong>el</strong>los residan don<strong>de</strong> han sido generados (y don<strong>de</strong> se<br />

entien<strong>de</strong> que son más requeridos); la i<strong>de</strong>a <strong>de</strong> mantener una copia <strong>de</strong> estos datos<br />

en otros lugares permite que puedan seguir las operaciones sobre los datos aún si<br />

alguno <strong>de</strong> estos sitios sufre algún <strong>de</strong>sastre. El estudio <strong>de</strong> este tipo <strong>de</strong><br />

<strong>de</strong>scentralización <strong>de</strong> los datos lleva al <strong>de</strong>sarrollo <strong>de</strong> los sistemas <strong>de</strong> base <strong>de</strong> datos<br />

distribuidos.<br />

3.3.1. SGBD centralizados.<br />

40


Un sistema <strong>de</strong> base <strong>de</strong> datos centralizado es aqu<strong>el</strong> que se ejecuta en un<br />

único sistema computacional sin tener, <strong>para</strong> tal efecto, que interactuar con otros<br />

computadores. El rango <strong>de</strong> estos sistemas compren<strong>de</strong> <strong>de</strong>s<strong>de</strong> los sistemas <strong>de</strong><br />

bases <strong>de</strong> datos monousuario ejecutándose en computadores personales hasta los<br />

sistemas <strong>de</strong> bases <strong>de</strong> datos ejecutándose en sistemas <strong>de</strong> alto rendimiento.<br />

Normalmente los sistemas <strong>de</strong> base <strong>de</strong> datos monousuarios no su<strong>el</strong>en<br />

proporcionar muchas <strong>de</strong> las facilida<strong>de</strong>s que ofrecen los sistemas multiusuario, en<br />

particular no tienen control <strong>de</strong> concurrencia y tienen precarios o inexistentes<br />

sistemas <strong>de</strong> recuperación.<br />

Dado que las maquinas en las cuales se utilizan los sistemas monousuarios<br />

son comúnmente computadores <strong>de</strong> propósito general, la arquitectura <strong>de</strong> estas<br />

maquinas es siempre parecida(<strong>de</strong> 1 a 2 procesadores que comparten la memoria<br />

principal) por tanto los sistemas <strong>de</strong> base <strong>de</strong> datos que se ejecutan sobre estas<br />

maquinas no intentan dividir una consulta simple entre los distintos procesadores,<br />

sino que ejecutan cada consulta en un único procesador posibilitando así la<br />

concurrencia <strong>de</strong> varias <strong>consultas</strong>. Este tipo <strong>de</strong> sistemas dan la sensación <strong>de</strong> una<br />

mayor productividad (puesto que pue<strong>de</strong>n ejecutar un mayor número <strong>de</strong><br />

transacciones por segundo) a pesar <strong>de</strong> que cada transacción individualmente no<br />

se ejecute más rápido. Por <strong>el</strong> contrario las máquinas <strong>para</strong>l<strong>el</strong>as tienen un gran<br />

número <strong>de</strong> procesadores y los sistemas <strong>de</strong> base <strong>de</strong> datos que ahí se ejecutan<br />

siempre ten<strong>de</strong>rán a <strong>para</strong>l<strong>el</strong>izar las tareas simples (<strong>consultas</strong>) que solicitan los<br />

usuarios.<br />

3.3.2. SGBD Cliente-Servidor.<br />

Con <strong>el</strong> crecimiento <strong>de</strong> los computadores personales (PC) y <strong>de</strong> las re<strong>de</strong>s <strong>de</strong><br />

área local (LAN), se han ido <strong>de</strong>splazando hacia <strong>el</strong> lado <strong>de</strong>l cliente la funcionalidad<br />

<strong>de</strong> la parte visible al usuario <strong>de</strong> la base <strong>de</strong> datos (interfaces <strong>de</strong> formularios, gestión<br />

41


<strong>de</strong> informes, etc.) <strong>de</strong> modo que los sistemas servidores provean la parte<br />

subyacente que tiene que ver con <strong>el</strong> acceso a las estructuras <strong>de</strong> datos, evaluación<br />

y procesamiento <strong>de</strong> <strong>consultas</strong>, control <strong>de</strong> concurrencia y recuperación. Los<br />

sistemas servidores pue<strong>de</strong>n dividirse en 2 tipos: los servidores transaccionales<br />

(que sirven <strong>para</strong> agrupar la lógica <strong>de</strong>l negocio en un servicio aparte, proveen una<br />

interfaz a través <strong>de</strong> la cual los clientes pue<strong>de</strong>n enviar peticiones como lo son<br />

ODBC 5 o RPC 6 ) y los servidores <strong>de</strong> datos(los cuales envían datos a más bajo niv<strong>el</strong><br />

y que <strong>de</strong>scansan en la capacidad <strong>de</strong> procesamiento <strong>de</strong> datos <strong>de</strong> las maquinas<br />

clientes).<br />

Existen 2 arquitecturas dominantes en la construcción <strong>de</strong> motores <strong>de</strong> base<br />

<strong>de</strong> datos cliente-servidor: los motores multiprocesos y los motores multihilos.<br />

3.3.2.1. Motores <strong>de</strong> base <strong>de</strong> datos multiprocesos (Multi-process database<br />

engines).<br />

Algunos motores <strong>de</strong> base <strong>de</strong> datos confían en múltiples aplicaciones <strong>para</strong><br />

realizar su trabajo. En este tipo <strong>de</strong> arquitectura, cada vez que un usuario se<br />

conecta a la base <strong>de</strong> datos, ésta inicia una nueva instancia <strong>de</strong> la aplicación <strong>de</strong><br />

base <strong>de</strong> datos. Con <strong>el</strong> fin <strong>de</strong> coordinar a muchos usuarios que accesan los mismos<br />

conjuntos <strong>de</strong> datos estos ejecutables trabajan con un coordinador global <strong>de</strong> tareas<br />

que planifica operaciones <strong>para</strong> todos los usuarios. La comunicación entre<br />

aplicaciones <strong>de</strong> este tipo se realiza por medio <strong>de</strong> un sistema propietario <strong>de</strong><br />

comunicaciones interprocesos (IPC).<br />

5 Open database conectivity: API <strong>de</strong> acceso a datos que soporta <strong>el</strong> acceso a cualquier<br />

fuente <strong>de</strong> datos <strong>para</strong> la cual exista un driver ODBC. ODBC se encuadra <strong>de</strong>ntro <strong>de</strong> los estándares<br />

ANSI e ISO <strong>para</strong> la Interfaz <strong>de</strong> llamadas <strong>de</strong> datos (CLI).<br />

6 Remote procedure call: Una forma <strong>de</strong> comunicación entre aplicaciones que escon<strong>de</strong> la<br />

complejidad <strong>de</strong> la red utilizando un mecanismo <strong>de</strong> llamada <strong>de</strong> procedimientos ordinario. Es un<br />

proceso sincrónico firmemente acoplado.<br />

42


El ejemplo más popular <strong>de</strong> motores <strong>de</strong> base <strong>de</strong> datos multiprocesos es <strong>el</strong><br />

Oracle Server (Oracle corporation) <strong>el</strong> cual carga 16 tipos <strong>de</strong> ejecutables distintos<br />

que realizan distintas tareas. El sistema ejecuta sus aplicaciones que sirven <strong>para</strong><br />

administrar <strong>el</strong> acceso <strong>de</strong> múltiples usuarios a las tablas, <strong>el</strong> registro y control <strong>de</strong><br />

versiones <strong>de</strong> una transacción y otras características como la replicación <strong>de</strong> datos,<br />

transacciones distribuidas. Por otro lado, cuando una conexión a la base <strong>de</strong> datos<br />

se establece, <strong>el</strong> sistema carga los ejecutables r<strong>el</strong>acionados a tareas <strong>de</strong> usuario.<br />

Cada vez que un usuario se conecta a una base <strong>de</strong> datos Oracle, esta<br />

carga un ejecutable con una nueva instancia <strong>de</strong> la base <strong>de</strong> datos, las <strong>consultas</strong> <strong>de</strong><br />

usuario son transmitidas a este ejecutable, <strong>el</strong> cual trabaja en conjunto con otros<br />

ejecutables en <strong>el</strong> servidor que retornan conjuntos <strong>de</strong> datos, manejan los bloqueos<br />

y ejecutan todas las funciones necesarias <strong>para</strong> <strong>el</strong> acceso <strong>de</strong> datos.<br />

La mayoría <strong>de</strong> los motores <strong>de</strong> base <strong>de</strong> datos multiprocesos fueron<br />

<strong>de</strong>sarrollados antes <strong>de</strong> que los sistemas operativos soportaran características<br />

tales como hilos o planificación <strong>de</strong> tareas (scheduling). Como resultado <strong>de</strong> esto, <strong>el</strong><br />

hecho <strong>de</strong> <strong>de</strong>scomponer una operación significaba escribir un ejecutable distinto<br />

<strong>para</strong> manejar esta operación. Esta característica proporciona <strong>el</strong> beneficio <strong>de</strong> la<br />

fácil escalabilidad a través <strong>de</strong> la adición <strong>de</strong> más CPUs.<br />

En un ambiente <strong>de</strong> multitarea <strong>el</strong> sistema operativo divi<strong>de</strong> <strong>el</strong> tiempo <strong>de</strong><br />

procesamiento entre múltiples aplicaciones asignándoles una porción <strong>de</strong> tiempo<br />

<strong>de</strong> CPU (“slice”) a cada una. De esta manera siempre hay una sola tarea<br />

ejecutándose a la vez, sin embargo <strong>el</strong> resultado es que múltiples aplicaciones<br />

aparenten estar corriendo simultáneamente en una sola CPU. La ventaja real, sin<br />

embargo, viene cuando <strong>el</strong> sistema operativo cuenta con múltiples CPUs.<br />

43


3.3.2.2. Motores <strong>de</strong> base <strong>de</strong> datos multihilos (Single-Process multi-threa<strong>de</strong>d<br />

database engines).<br />

Los motores <strong>de</strong> base <strong>de</strong> datos multihilos abordan <strong>el</strong> problema <strong>de</strong>l acceso<br />

multiusuario <strong>de</strong> una manera distinta, pero con principios similares. En lugar <strong>de</strong><br />

confiar en que <strong>el</strong> sistema operativo comparta los recursos <strong>de</strong> procesamiento, <strong>el</strong><br />

motor toma la responsabilidad por sí mismo, lo que en la práctica se asocia a una<br />

mejor portabilidad <strong>de</strong>l sistema. Motores <strong>de</strong> base <strong>de</strong> datos comerciales como<br />

Sybase Adaptive Server o Microsoft Sql Server son ejemplos <strong>de</strong> este enfoque.<br />

Las ventajas <strong>de</strong> este tipo <strong>de</strong> motores radican en una mayor eficiencia en <strong>el</strong><br />

uso <strong>de</strong> recursos <strong>para</strong> <strong>de</strong>terminadas plataformas. Mientas un sistema<br />

multiprocesos consume entre 500 Kb y 1 Mb por conexión, un motor multihilos<br />

consume entre 50 y 100 Kb <strong>de</strong> RAM diferencia que pue<strong>de</strong> ser utilizada en caché<br />

<strong>de</strong> datos y procedimientos. Otra ventaja es que no hay necesidad <strong>de</strong> un<br />

mecanismo <strong>de</strong> comunicación interprocesos.<br />

De esta manera, la base <strong>de</strong> datos utiliza un <strong>el</strong>emento finito <strong>de</strong> trabajo, (<strong>el</strong><br />

hilo) <strong>para</strong> una variedad <strong>de</strong> operaciones (instrucciones <strong>de</strong> usuarios, bloqueos <strong>de</strong><br />

datos, E/S <strong>de</strong> disco, administración <strong>de</strong>l caché, etc.) en vez <strong>de</strong> utilizar aplicaciones<br />

especializadas <strong>para</strong> cada tarea.<br />

Las <strong>de</strong>sventajas más reconocidas son dos: escalabilidad y portabilidad. La<br />

escalabilidad se centra en la habilidad que tengan los distintos motores <strong>de</strong> base <strong>de</strong><br />

datos multihilos <strong>de</strong> <strong>de</strong>scomponer una operación <strong>de</strong> manera que múltiples tareas<br />

puedan ejecutar esta operación.<br />

Los problemas <strong>de</strong> portabilidad guardan r<strong>el</strong>ación con <strong>el</strong> SMP<br />

(multiprocesamiento simétrico) y se originan en <strong>el</strong> hecho <strong>de</strong> que dado que<br />

diferentes fabricantes <strong>de</strong> hardware dan soporte a SMP <strong>de</strong> diferentes maneras,<br />

44


estos motores <strong>de</strong> base <strong>de</strong> datos han tenido que implementar técnicas neutras que<br />

buscan funcionar bien en cualquier implementación física, lo que conlleva una<br />

sobrecarga en <strong>el</strong> motor y una limitación en la habilidad <strong>de</strong> escalar a un gran<br />

número <strong>de</strong> procesadores.<br />

3.3.3. SGBD Paral<strong>el</strong>os.<br />

Los sistemas <strong>para</strong>l<strong>el</strong>os <strong>de</strong> base <strong>de</strong> datos constan <strong>de</strong> varios procesadores y<br />

varios discos conectados a través <strong>de</strong> una red <strong>de</strong> interconexión <strong>de</strong> alta v<strong>el</strong>ocidad.<br />

Para medir <strong>el</strong> rendimiento <strong>de</strong> los sistemas <strong>de</strong> base <strong>de</strong> datos existen 2 medidas<br />

principales: la primera es la productividad (throughput) que se entien<strong>de</strong> como <strong>el</strong><br />

número <strong>de</strong> tareas que pue<strong>de</strong>n completarse en un intervalo <strong>de</strong> tiempo <strong>de</strong>terminado.<br />

La segunda es <strong>el</strong> tiempo <strong>de</strong> respuesta (response time) que es la cantidad <strong>de</strong><br />

tiempo que necesita <strong>para</strong> completar una única tarea a partir <strong>de</strong>l momento en que<br />

se envíe. Un sistema que procese un gran número <strong>de</strong> pequeñas transacciones<br />

pue<strong>de</strong> mejorar su productividad realizando muchas transacciones en <strong>para</strong>l<strong>el</strong>o. Un<br />

sistema que procese transacciones más largas pue<strong>de</strong> mejorar tanto su<br />

productividad como sus tiempos <strong>de</strong> respuesta realizando en <strong>para</strong>l<strong>el</strong>o cada una <strong>de</strong><br />

las subtareas <strong>de</strong> cada transacción.<br />

Las ganancias en este tipo <strong>de</strong> SGBD se pue<strong>de</strong>n dar en términos <strong>de</strong> v<strong>el</strong>ocidad<br />

(menor tiempo <strong>de</strong> ejecución <strong>para</strong> una tarea dada) y ampliabilidad (capacidad <strong>de</strong><br />

procesar tareas más largas en <strong>el</strong> mismo tiempo).<br />

Existen varios mo<strong>de</strong>los <strong>de</strong> arquitecturas <strong>para</strong> maquinas <strong>para</strong>l<strong>el</strong>as, los más<br />

mencionados son:<br />

• Memoria Compartida : Todos los procesadores comparten una memoria<br />

común.<br />

45


• Disco Compartido: Todos los procesadores comparten una disposición <strong>de</strong><br />

discos común.<br />

• Sin Compartimiento: Los procesadores no comparten ni memoria ni disco.<br />

• Jerárquico: Compartimiento tanto <strong>de</strong> memoria como <strong>de</strong> disco.<br />

3.3.4. SGBD Distribuidos.<br />

En un SGBD distribuido, la base <strong>de</strong> datos se almacena en varios<br />

computadores que se pue<strong>de</strong>n comunicar a sus vez por distintos medios <strong>de</strong><br />

comunicación (<strong>de</strong>s<strong>de</strong> re<strong>de</strong>s <strong>de</strong> alta v<strong>el</strong>ocidad a líneas t<strong>el</strong>efónicas). No comparten<br />

memoria ni discos y sus tamaños pue<strong>de</strong>n variar tanto como sus funciones<br />

pudiendo abarcar <strong>de</strong>s<strong>de</strong> PC hasta gran<strong>de</strong>s sistemas. Se <strong>de</strong>nomina con <strong>el</strong> término<br />

<strong>de</strong> emplazamientos o nodos a todos aqu<strong>el</strong>los computadores que pertenecen a un<br />

sistema distribuido.<br />

Las principales diferencias entre las bases <strong>de</strong> datos <strong>para</strong>l<strong>el</strong>as y las bases<br />

<strong>de</strong> datos distribuidas son las siguientes: las bases <strong>de</strong> datos distribuidas se<br />

encuentran normalmente en varios lugares geográficos distintos, se administran<br />

<strong>de</strong> forma se<strong>para</strong>da y poseen una interconexión más lenta. Otra diferencia es que<br />

en un sistema distribuido se dan dos tipos <strong>de</strong> transacciones, las locales y las<br />

globales. Una transacción local es aqu<strong>el</strong>la que acce<strong>de</strong> a los datos <strong>de</strong>l único<br />

emplazamiento en <strong>el</strong> cual se inició la transacción. Por otra parte una transacción<br />

global es aqu<strong>el</strong>la que o bien acce<strong>de</strong> a los datos situados en un emplazamiento<br />

diferente <strong>de</strong> aqu<strong>el</strong> en <strong>el</strong> que se inició la transacción, o bien acce<strong>de</strong> a datos <strong>de</strong><br />

varios emplazamientos distintos.<br />

Un sistema <strong>de</strong> base <strong>de</strong> datos distribuido se conoce por:<br />

• Los distintos emplazamientos están informados <strong>de</strong> los <strong>de</strong>más.<br />

46


• Aunque algunas r<strong>el</strong>aciones pue<strong>de</strong>n estar almacenadas sólo en algunos<br />

emplazamientos, éstos comparten un esquema global común.<br />

• Cada emplazamiento proporciona un entorno <strong>para</strong> la ejecución <strong>de</strong><br />

transacciones tanto locales como globales.<br />

47


Capítulo 4. Introducción al Procesamiento <strong>de</strong> Consultas,<br />

El enfoque <strong>de</strong> System R.<br />

4.1. Introducción.<br />

El Procesamiento <strong>de</strong> <strong>consultas</strong> hace referencia a la serie <strong>de</strong> activida<strong>de</strong>s a<br />

seguir <strong>para</strong> llevar a cabo la recuperación <strong>de</strong> datos <strong>de</strong>s<strong>de</strong> una base <strong>de</strong> datos. Estas<br />

activida<strong>de</strong>s incluyen la traducción <strong>de</strong> <strong>consultas</strong> en <strong>lenguaje</strong>s <strong>de</strong> <strong>consultas</strong> <strong>de</strong> alto<br />

niv<strong>el</strong> (Ej: SQL) a expresiones que se puedan implementar en un niv<strong>el</strong> físico, así<br />

como también los algoritmos <strong>de</strong> evaluación y optimización <strong>de</strong> <strong>consultas</strong>.<br />

Una <strong>de</strong> las ventajas principales <strong>de</strong>l mo<strong>de</strong>lo r<strong>el</strong>acional presentado por Codd<br />

en 1970 es la que tiene r<strong>el</strong>ación con la in<strong>de</strong>pen<strong>de</strong>ncia <strong>de</strong> los datos que se<br />

entien<strong>de</strong> aquí como la se<strong>para</strong>ción entre <strong>el</strong> mo<strong>de</strong>lo (lógico) y la implementación<br />

(física). Esta se<strong>para</strong>ción nos permite <strong>de</strong>sarrollar una po<strong>de</strong>rosa semántica lógica<br />

in<strong>de</strong>pendiente <strong>de</strong> una implementación física particular.<br />

Uno <strong>de</strong> los <strong>de</strong>safíos <strong>de</strong> la in<strong>de</strong>pen<strong>de</strong>ncia <strong>de</strong> datos es que la codificación <strong>de</strong><br />

una consulta <strong>para</strong> la base <strong>de</strong> datos se componga <strong>de</strong> 2 fases:<br />

1. La <strong>de</strong>scripción lógica <strong>de</strong> la consulta (que se supone que <strong>de</strong>be hacer).<br />

2. La <strong>de</strong>finición <strong>de</strong>l plan <strong>de</strong> ejecución físico (<strong>el</strong> que muestra como implementar la<br />

consulta).<br />

Antes <strong>de</strong> empezar <strong>el</strong> Procesamiento <strong>de</strong> la consulta <strong>el</strong> sistema <strong>de</strong>be traducir<br />

la consulta a un medio <strong>de</strong> representación interno con <strong>el</strong> cual le sea fácil operar.<br />

48


Así, por ejemplo <strong>para</strong> SQL la representación más útil es la <strong>de</strong>l álgebra r<strong>el</strong>acional<br />

extendida (árbol r<strong>el</strong>acional). Este proceso cumple la misma función que <strong>el</strong><br />

analizador léxico y sintáctico <strong>de</strong> un compilador, es <strong>de</strong>cir, revisa la sintaxis <strong>de</strong> la<br />

consulta y chequea que todos lo i<strong>de</strong>ntificadores sean nombres <strong>de</strong> objetos <strong>de</strong> la<br />

base <strong>de</strong> datos, en <strong>el</strong> caso <strong>de</strong> las vistas reemplaza <strong>el</strong> nombre <strong>de</strong> la vista por la<br />

expresión r<strong>el</strong>acional que la representa.<br />

El plan <strong>de</strong> ejecución es un árbol r<strong>el</strong>acional armado a partir <strong>de</strong> la consulta y<br />

que sólo pue<strong>de</strong> ser entendido por <strong>el</strong> motor <strong>de</strong> ejecución <strong>de</strong> <strong>consultas</strong>. La<br />

transformación <strong>de</strong> la consulta a un plan pue<strong>de</strong> ser hecha efectivamente a mano y<br />

en algunos casos <strong>de</strong> <strong>consultas</strong> simples que se ejecutan miles <strong>de</strong> veces esta<br />

podría ser la mejor estrategia, sin embargo, una <strong>de</strong> las ventajas que nos ofrece <strong>el</strong><br />

mo<strong>de</strong>lo r<strong>el</strong>acional es la capacidad <strong>de</strong> usar la información <strong>de</strong>l catalogo <strong>de</strong> la base<br />

<strong>de</strong> datos, que como se verá más a<strong>de</strong>lante, podrá respon<strong>de</strong>r una gran cantidad <strong>de</strong><br />

preguntas distintas.<br />

Por otro lado, aunque una consulta simple pueda ser ejecutada miles <strong>de</strong><br />

veces, no existe un camino mecánico que garantice que <strong>el</strong> plan <strong>de</strong> ejecución<br />

<strong>el</strong>egido satisfaga la consulta que se quiere implementar, puesto que:<br />

1. Un Plan calculado a mano (o un plan precalculado) será invalidado por<br />

cambios lógicos <strong>de</strong>ntro <strong>de</strong>l esquema o por cambios físicos en <strong>el</strong> camino <strong>de</strong><br />

acceso a la información o en <strong>el</strong> almacenamiento físico.<br />

2. Si los parámetros <strong>de</strong> la consulta (o los datos) cambian, la r<strong>el</strong>ación optima que<br />

asocia a un plan con una consulta por sobre otros pue<strong>de</strong> cambiar.<br />

La siguiente figura nos muestra los pasos en <strong>el</strong> procesamiento <strong>de</strong> una<br />

consulta.<br />

49


Consulta<br />

Resultado<br />

<strong>de</strong> la Consulta<br />

Analizador y<br />

traductor<br />

(parser)<br />

Datos<br />

Motor <strong>de</strong><br />

Ejecución<br />

Información <strong>de</strong>l<br />

Catalogo<br />

Figura 4-1 - Pasos en <strong>el</strong> procesamiento <strong>de</strong> una consulta SQL<br />

Expresión en Algebra<br />

R<strong>el</strong>acional<br />

(Arbol r<strong>el</strong>acional)<br />

Optimizador<br />

Plan <strong>de</strong><br />

Ejecución<br />

Después <strong>de</strong> enviar la consulta, la base <strong>de</strong> datos <strong>de</strong>be producir su<br />

correspondiente plan <strong>de</strong> ejecución. El primer paso en este proceso es traducir la<br />

consulta <strong>de</strong>s<strong>de</strong> SQL a un árbol lógico en álgebra r<strong>el</strong>acional, proceso comúnmente<br />

llamado parser.<br />

El Próximo paso es traducir <strong>el</strong> árbol <strong>de</strong> la consulta en <strong>el</strong> plan <strong>de</strong> ejecución.<br />

Generalmente existe un gran número <strong>de</strong> planes que implementan al árbol <strong>de</strong> la<br />

consulta; <strong>el</strong> proceso <strong>de</strong> encontrar <strong>el</strong> mejor <strong>de</strong> estos planes se le <strong>de</strong>nomina<br />

optimización <strong>de</strong> <strong>consultas</strong>, entendiéndose que esta optimización viene dada por<br />

una medida <strong>de</strong> rendimiento <strong>para</strong> la ejecución <strong>de</strong> <strong>consultas</strong> (como por ejemplo <strong>el</strong><br />

tiempo <strong>de</strong> ejecución), queremos encontrar entonces la consulta que tenga <strong>el</strong> mejor<br />

rendimiento <strong>de</strong> ejecución. El objetivo es que <strong>el</strong> plan sea <strong>el</strong> óptimo (o <strong>el</strong> más<br />

cercano a) dado <strong>el</strong> espacio <strong>de</strong> búsqueda <strong>de</strong>l optimizador.<br />

50


Finalmente <strong>el</strong> optimizador envía <strong>el</strong> plan óptimo al motor <strong>de</strong> ejecución. El<br />

motor <strong>de</strong> ejecución ejecuta <strong>el</strong> plan usando como entrada las r<strong>el</strong>aciones<br />

almacenadas en las base <strong>de</strong> datos y produce una tabla con los datos solicitados<br />

como salida.<br />

Los primeros optimizadores <strong>de</strong> <strong>consultas</strong> fueron <strong>de</strong>scritos <strong>para</strong> System R<br />

[S<strong>el</strong>inger79] y <strong>para</strong> Ingress [Wong76] en los años 1979 y 1976 respectivamente.<br />

Estos fueron implementados <strong>para</strong> variantes particulares <strong>de</strong>l mo<strong>de</strong>lo R<strong>el</strong>acional y<br />

funcionan lo suficientemente bien en la medida <strong>de</strong> sus implementaciones físicas<br />

<strong>de</strong>l mo<strong>de</strong>lo. El Optimizador <strong>de</strong> System R ha sido la base <strong>de</strong> otros optimizadores <strong>de</strong><br />

bases <strong>de</strong> datos comerciales.<br />

4.2. El optimizador <strong>de</strong> System R.<br />

[S<strong>el</strong>inger79] propone una <strong>de</strong>scomposición <strong>de</strong> 4 fases en <strong>el</strong> procesamiento<br />

<strong>de</strong> una consulta SQL: parsing, optimización, generación <strong>de</strong> código y ejecución. Al<br />

principio cada sentencia SQL es enviada al parser (analizador sintáctico), quien se<br />

encarga <strong>de</strong> chequear la sintaxis <strong>de</strong> la consulta; si no hay errores, <strong>el</strong> parser llama<br />

al optimizador, quien toma todos los nombres <strong>de</strong> tablas y columnas referenciadas<br />

por la consulta y las busca en <strong>el</strong> catalogo <strong>de</strong> la BD <strong>para</strong> verificar su existencia y<br />

rescatar estadísticas y caminos <strong>de</strong> accesos almacenados. Es <strong>el</strong> optimizador quien<br />

también analiza los tipos <strong>de</strong> datos y tamaños <strong>de</strong> cada columna con <strong>el</strong> fin <strong>de</strong> revisar<br />

en la lista SELECT 7 como en <strong>el</strong> Arbol WHERE 8 la existencia <strong>de</strong> errores <strong>de</strong><br />

semántica e incompatibilida<strong>de</strong>s <strong>de</strong> tipos <strong>de</strong> datos.<br />

7 Lista <strong>de</strong> todos los <strong>el</strong>ementos que están en una cláusula s<strong>el</strong>ect.<br />

8<br />

Estructura <strong>de</strong> árbol que contiene todos los predicados contenidos en la clausula<br />

WHERE.<br />

51


Finalmente realiza la s<strong>el</strong>ección <strong>de</strong> los caminos <strong>de</strong> acceso. Si una consulta<br />

tiene más <strong>de</strong> un query block 9 (en a<strong>de</strong>lante bloque) <strong>de</strong>termina <strong>el</strong> or<strong>de</strong>n <strong>de</strong><br />

evaluación <strong>de</strong> estos a lo largo <strong>de</strong> la consulta, luego procesa <strong>para</strong> cada bloque las<br />

r<strong>el</strong>aciones enunciadas en la lista FROM 10 . Si en <strong>el</strong> bloque existe más <strong>de</strong> una<br />

r<strong>el</strong>ación, <strong>el</strong> optimizador realiza permutaciones <strong>de</strong> los métodos <strong>de</strong> join, por tanto, se<br />

<strong>el</strong>ige <strong>el</strong> camino <strong>de</strong> acceso que minimice <strong>el</strong> costo <strong>para</strong> <strong>el</strong> bloque. Esta solución<br />

recibe <strong>el</strong> nombre <strong>de</strong> “plan <strong>de</strong> ejecución” [S<strong>el</strong>inger79] <strong>el</strong> cual se representa en <strong>el</strong><br />

<strong>lenguaje</strong> <strong>de</strong> especificación <strong>de</strong> accesos (ASL) cuya <strong>de</strong>finición queda fuera <strong>de</strong> los<br />

alcances <strong>de</strong> este trabajo. Para mayor Información consultar [Lorie78].<br />

El generador <strong>de</strong> código es un programa que traslada árboles ASL en<br />

<strong>lenguaje</strong> <strong>de</strong> máquina <strong>para</strong> ejecutar <strong>el</strong> plan escogido por <strong>el</strong> optimizador, <strong>para</strong> hacer<br />

esto utiliza un pequeño número <strong>de</strong> plantillas <strong>de</strong> código <strong>para</strong> representar todos los<br />

casos posibles, durante esta fase se reemplaza <strong>el</strong> árbol generado por <strong>el</strong> parser en<br />

código <strong>de</strong> maquina ejecutable y sus estructuras <strong>de</strong> datos asociadas.<br />

4.2.1. RSS (research storage system)<br />

El RSS es <strong>el</strong> subsistema <strong>de</strong> almacenamiento <strong>de</strong> system R, este es <strong>el</strong><br />

responsable <strong>de</strong> mantener <strong>el</strong> almacenamiento físico <strong>de</strong> las r<strong>el</strong>aciones, <strong>de</strong> los<br />

caminos <strong>de</strong> acceso a <strong>el</strong>las, bloqueos (en un ambiente multiusuario), y <strong>de</strong> las<br />

capacida<strong>de</strong>s <strong>de</strong> registro <strong>de</strong> transacciones y recuperación. El RSI (Research<br />

Storage Interface) es la interfaz orientada a la tupla que system R presenta al<br />

usuario final.<br />

9<br />

Un query block es un bloque <strong>de</strong> cláusulas que conforman una consulta sql <strong>de</strong> la forma<br />

SELECT, FROM, WHERE, GROUP BY, ORDER BY.<br />

10 Lista <strong>de</strong> todas las r<strong>el</strong>aciones enunciadas en la clausula FROM <strong>de</strong> una consulta sql.<br />

52


Una R<strong>el</strong>ación se almacena en <strong>el</strong> RSS como una colección <strong>de</strong> tuplas que<br />

cumplen con las siguientes características:<br />

• sus columnas son contiguas,<br />

• se almacenan en páginas <strong>de</strong> 4 Kb,<br />

• una tupla no pue<strong>de</strong> rebasar una página.<br />

Las páginas se organizan en segmentos, los segmentos pue<strong>de</strong>n contener<br />

una o más r<strong>el</strong>aciones pero una r<strong>el</strong>ación no pue<strong>de</strong> rebasar un segmento.<br />

La manera <strong>de</strong> accesar tuplas <strong>de</strong> una r<strong>el</strong>ación es por medio <strong>de</strong> un proceso<br />

llamado RSS scan, este retorna una tupla a la vez a lo largo <strong>de</strong>l camino <strong>de</strong> acceso<br />

indicado. Los comandos principales son: OPEN, NEXT y CLOSE.<br />

Existen 2 tipos <strong>de</strong> recorridos (scan), <strong>el</strong> primero es un segment scan, <strong>el</strong> cual<br />

encuentra todas las tuplas <strong>de</strong> una r<strong>el</strong>ación dada, consiste básicamente <strong>de</strong> una<br />

serie <strong>de</strong> NEXT que recorren todas las páginas <strong>de</strong>l segmento (que pue<strong>de</strong>n<br />

contener tuplas <strong>para</strong> cualquier r<strong>el</strong>ación) y <strong>de</strong> don<strong>de</strong> rescatan aqu<strong>el</strong>las tuplas que<br />

pertenecen a la r<strong>el</strong>ación dada.<br />

El segundo tipo <strong>de</strong> recorrido es un in<strong>de</strong>x scan 11 , los índices se almacenan<br />

en páginas distintas a las páginas <strong>de</strong> datos y son implementados como B-tree<br />

cuyas hojas <strong>de</strong>l árbol son páginas que contienen conjuntos <strong>de</strong> ya sea claves,<br />

i<strong>de</strong>ntificadores, o tuplas que contienen la clave; por lo tanto una serie <strong>de</strong> NEXT<br />

sobre un “in<strong>de</strong>x scan”, realiza una lectura secuencial a lo largo <strong>de</strong> las hojas<br />

obteniendo las tuplas <strong>de</strong> i<strong>de</strong>ntificadores que se igualan a la clave <strong>de</strong> búsqueda o<br />

usándolas <strong>para</strong> encontrar y retornar las tuplas <strong>de</strong> datos en <strong>el</strong> or<strong>de</strong>n <strong>de</strong> las claves<br />

11 un índice pue<strong>de</strong> ser creado por un usuario <strong>de</strong> system R en una o más columnas <strong>de</strong> una<br />

r<strong>el</strong>ación, y una r<strong>el</strong>ación pue<strong>de</strong> cero o más índices asociados a esta.<br />

53


dadas. Las paginas <strong>de</strong> índices están enca<strong>de</strong>nas juntas, por lo tanto las sentencias<br />

NEXT no necesitan referenciar paginas que se encuentren más arriba <strong>de</strong>l índice.<br />

En un “segment scan” todas las páginas no vacías <strong>de</strong> un segmento se<br />

accesan sólo una vez sin importar si tienen o no tuplas que pertenezcan a la<br />

r<strong>el</strong>ación. En un “in<strong>de</strong>x scan” las páginas <strong>de</strong> índices se accesan sólo una vez, sin<br />

embargo las páginas <strong>de</strong> datos se pue<strong>de</strong>n tocar más <strong>de</strong> una vez.<br />

Si las tuplas han sido insertadas en las paginas <strong>de</strong>l segmento en <strong>el</strong> or<strong>de</strong>n<br />

<strong>de</strong>l índice y si este or<strong>de</strong>n se mantiene diremos que <strong>el</strong> índice es un índice en<br />

cluster, este tipo <strong>de</strong> índices tiene la propiedad <strong>de</strong> que a<strong>de</strong>más <strong>de</strong> las paginas <strong>de</strong><br />

índices, también las paginas <strong>de</strong> datos se accesan solamente una vez en un “in<strong>de</strong>x<br />

scan”. Cabe <strong>de</strong>stacar <strong>de</strong> que un “in<strong>de</strong>x scan” no necesita recorrer toda la r<strong>el</strong>ación,<br />

pues pue<strong>de</strong> recibir llaves <strong>de</strong> inicio y fin.<br />

Ambos tipos <strong>de</strong> scan pue<strong>de</strong>n recibir un conjunto <strong>de</strong> predicados llamados<br />

predicados sargables o SARGS (“search arguments”) los cuales tiene la<br />

particularidad <strong>de</strong> que son aplicados a las tuplas antes <strong>de</strong> que sean <strong>de</strong>vu<strong>el</strong>tas al<br />

RSI. Un predicado sargable es uno <strong>de</strong> la forma:<br />

“columna operador_<strong>de</strong>_com<strong>para</strong>ción valor”.<br />

4.2.2. Costos <strong>para</strong> los caminos <strong>de</strong> acceso <strong>de</strong> r<strong>el</strong>aciones simples.<br />

El optimizador <strong>de</strong> System trata <strong>de</strong> manera distinta a las <strong>consultas</strong> que<br />

hacen referencia a una sola tabla (r<strong>el</strong>aciones simples) <strong>de</strong> las que se <strong>de</strong>ben tratar<br />

como un Join. Para <strong>el</strong> primer caso, <strong>el</strong> optimizador examina tanto los predicados <strong>de</strong><br />

la consulta como también los caminos <strong>de</strong> acceso disponibles <strong>para</strong> la r<strong>el</strong>ación<br />

referenciada y evalúa una fórmula <strong>de</strong> costo <strong>para</strong> cada plan <strong>de</strong> acceso usando la<br />

siguiente fórmula:<br />

54


COSTO = Páginas Rescatadas + W * (RSI calls)<br />

Este costo es una medida <strong>de</strong> peso entre las E/S (páginas rescatadas) y la<br />

utilización <strong>de</strong> CPU (instrucciones ejecutadas). W es un factor <strong>de</strong> peso ajustable<br />

entre E/S y la CPU 12 . RSI calls es la estimación <strong>de</strong>l número <strong>de</strong> tuplas a retornar.<br />

Dada esta formula la <strong>el</strong>ección <strong>de</strong>l camino <strong>de</strong> costo mínimo <strong>para</strong> procesar una<br />

consulta tien<strong>de</strong> a minimizar <strong>el</strong> total <strong>de</strong> recursos requeridos.<br />

La ejecución <strong>de</strong> la validación semántica <strong>de</strong>l optimizador examina cada<br />

bloque WHERE (<strong>el</strong> respectivo árbol <strong>de</strong>be estar en la forma normal conjuntiva) con<br />

<strong>el</strong> objetivo <strong>de</strong> i<strong>de</strong>ntificar los factores booleanos.<br />

Se llama factor booleano a cada uno <strong>de</strong> los predicados <strong>de</strong>l Arbol WHERE (o<br />

conjunciones) que ha sido previamente normalizado.<br />

Se dice que un índice calza un factor booleano si <strong>el</strong> factor booleano es un<br />

predicado sargable cuya columna referenciada es la clave <strong>de</strong>l índice.<br />

Se dice que un predicado o un conjunto <strong>de</strong> predicados calza a un camino<br />

<strong>de</strong> acceso por índice cuando los predicados son sargables y las columnas<br />

mencionadas en los predicados son un substring inicial <strong>de</strong>l conjunto <strong>de</strong> columnas<br />

<strong>de</strong> la clave <strong>de</strong>l índice. Si un índice calza un factor booleano entonces un camino<br />

<strong>de</strong> acceso que ocupe este índice será una manera eficiente <strong>de</strong> satisfacer <strong>el</strong> factor<br />

booleano.<br />

12 Una forma <strong>de</strong> calcularlo pue<strong>de</strong> ser tomar los MIPS <strong>de</strong> una <strong>de</strong>terminada CPU y por otro<br />

lado tomar <strong>el</strong> número <strong>de</strong> instrucciones que se utilizan en una llamada RSS. W podría ser <strong>el</strong><br />

producto <strong>de</strong> estos 2 valores medidos durante <strong>el</strong> tiempo transcurrido en una búsqueda típica a<br />

disco. Por lo tanto W tendrá diferentes valores <strong>de</strong>pendiendo <strong>de</strong> distintas configuraciones <strong>de</strong><br />

hardware. (Don Chamberlin, 12/09/2001)<br />

55


Durante la mirada al catálogo, <strong>el</strong> optimizador recupera estadísticas <strong>para</strong> las<br />

r<strong>el</strong>aciones <strong>de</strong> la consulta y caminos <strong>de</strong> acceso disponibles <strong>para</strong> cada r<strong>el</strong>ación. Las<br />

estadísticas son las siguientes:<br />

Para cada r<strong>el</strong>ación T.<br />

• NCARD(T), cardinalidad <strong>de</strong> la r<strong>el</strong>ación T.<br />

• TCARD(T), número <strong>de</strong> páginas <strong>de</strong>l segmento que contienen tuplas<br />

<strong>de</strong> la r<strong>el</strong>ación T.<br />

• P(T), fracción <strong>de</strong> paginas <strong>de</strong> datos que contienen tuplas <strong>de</strong> la<br />

r<strong>el</strong>ación T.<br />

P(T) = TCARD(T)/Número_<strong>de</strong>_páginas_no_vacías_en_<strong>el</strong>_segmento.<br />

Para Cada índice en la r<strong>el</strong>ación T.<br />

• ICARD(I), Número <strong>de</strong> claves distintas en <strong>el</strong> índice I<br />

• NINDEX(I), Número <strong>de</strong> páginas en <strong>el</strong> índice I.<br />

Estas estadísticas son mantenidas por <strong>el</strong> catálogo <strong>de</strong> System R, y<br />

provienen <strong>de</strong> distintas fuentes, son actualizadas periódicamente por <strong>el</strong> comando<br />

UPDATE STATISTICS, <strong>el</strong> cual pue<strong>de</strong> ser ejecutado por cualquier usuario.<br />

Usando estas estadísticas, <strong>el</strong> optimizador asigna un factor <strong>de</strong> s<strong>el</strong>ección “F”<br />

<strong>para</strong> cada factor booleano en la lista <strong>de</strong> predicados. Este factor es la estimación<br />

<strong>de</strong> la cantidad <strong>de</strong> tuplas que satisfacen <strong>el</strong> predicado. Se asume que una falta <strong>de</strong><br />

estadísticas implica la <strong>el</strong>ección <strong>de</strong> un factor arbitrario.<br />

56


La siguiente tabla muestra los factores a utilizar <strong>para</strong> los distintos tipos <strong>de</strong><br />

predicados:<br />

columna = valor<br />

F = 1 / ICARD(índice) si existe un índice <strong>para</strong> la columna. Esto asume<br />

una distribución uniforme <strong>de</strong> los datos a lo largo <strong>de</strong>l dominio <strong>de</strong> la<br />

columna.<br />

F = 1 / 10 en otro caso.<br />

columna1 = columna2<br />

F = 1 / MAX(ICARD(índice_columna1), ICARD(índice_columna2)) si existen<br />

índices tanto en columna1 como en columna2. Esto asume que cada valor<br />

en <strong>el</strong> dominio <strong>de</strong>l índice con menor cardinalidad se iguala a un valor<br />

en <strong>el</strong> otro índice.<br />

F = 1 / ICARD(indice_columna-i) si sólo existe un índice sobre la<br />

columna-i<br />

F = 1 / 10 en otro caso<br />

Columna > valor (o cualquier otra com<strong>para</strong>ción abierta)<br />

F = (mayor_valor_dominio – valor) / (mayor_valor_dominio –<br />

menor_valor_dominio) si la columna es <strong>de</strong> tipo aritmético y <strong>el</strong> valor<br />

es conocido en <strong>el</strong> momento <strong>de</strong> escoger <strong>el</strong> camino <strong>de</strong> acceso.<br />

mayor_valor y menor_valor son los límites <strong>de</strong>l dominio.<br />

F = 1 / 3 en otro caso. Respon<strong>de</strong> a la hipótesis <strong>de</strong> que son menos las<br />

<strong>consultas</strong> que usan predicados que son satisfechos por más <strong>de</strong> la mitad<br />

<strong>de</strong> las tuplas.<br />

Columna between valor1 and valor2<br />

F = (valor2 – valor1) / (mayor_valor_dominio – menor_valor_dominio)<br />

que correspon<strong>de</strong> a una razón entre <strong>el</strong> rango <strong>de</strong> valores <strong>de</strong> la cláusula<br />

57


BETWEEN con respecto al rango <strong>de</strong> valores <strong>de</strong>l dominio siempre que la<br />

columna sea aritmética y ambos valores sean conocidos al momento <strong>de</strong><br />

escoger <strong>el</strong> camino <strong>de</strong> acceso.<br />

F = 1 / 4 en otro caso.<br />

Columna in (lista_<strong>de</strong>_valores)<br />

F = (numero_<strong>de</strong>_<strong>el</strong>ementos_<strong>de</strong>_la_lista) * (factor_<strong>de</strong>_s<strong>el</strong>ección <strong>para</strong><br />

columna = valor) siempre y cuando no sea mayor que ½.<br />

Columna in subconsulta<br />

F = (cardinalidad estimada <strong>de</strong> la subconsulta) / (producto <strong>de</strong> las<br />

cardinalida<strong>de</strong>s<br />

subconsulta)<br />

<strong>de</strong> todas las r<strong>el</strong>aciones <strong>de</strong> la lista FROM <strong>de</strong> la<br />

El cálculo <strong>de</strong> la cardinalidad <strong>de</strong> una subconsulta se explica más<br />

a<strong>de</strong>lante.<br />

Predicado1 OR predicado2<br />

F = F(predicado1) + F(predicado2) – F(predicado1) * F(predicado2)<br />

Predicado1 AND predicado2<br />

F = F(predicado1) * F(predicado2)<br />

NOT predicado<br />

F = 1 – F(predicado)<br />

Tabla 4-1 - Factores <strong>de</strong> S<strong>el</strong>ección <strong>para</strong> caminos <strong>de</strong> acceso a R<strong>el</strong>aciones Simples.<br />

La cardinalidad <strong>de</strong> una consulta (QCARD) es <strong>el</strong> producto <strong>de</strong> las<br />

cardinalida<strong>de</strong>s <strong>de</strong> cada r<strong>el</strong>ación involucrada multiplicado por <strong>el</strong> producto <strong>de</strong> todos<br />

los factores <strong>de</strong> s<strong>el</strong>ección. El número esperado <strong>de</strong> llamadas RSI (RSICARD) es <strong>el</strong><br />

producto <strong>de</strong> las cardinalida<strong>de</strong>s <strong>de</strong> las r<strong>el</strong>aciones por los factores <strong>de</strong> s<strong>el</strong>ección <strong>de</strong><br />

58


todos los factores booleanos sargables (dado que estos argumentos son los que<br />

se aplican antes <strong>de</strong> ser retornadas a la RSI).<br />

El escoger <strong>el</strong> camino <strong>de</strong> acceso óptimo <strong>para</strong> una r<strong>el</strong>ación consiste entonces<br />

en usar estos factores <strong>de</strong> s<strong>el</strong>ección junto con las estadísticas <strong>de</strong>l catalogo en<br />

fórmulas <strong>de</strong>finidas. Para llegar a estas fórmulas se presentara entonces la<br />

siguiente <strong>de</strong>finición.<br />

Se dice que un <strong>de</strong>terminado or<strong>de</strong>n <strong>de</strong> tuplas es un “interesting or<strong>de</strong>r” si este<br />

or<strong>de</strong>n es uno <strong>de</strong> los especificados en las cláusulas GROUP BY u ORDER BY.<br />

Para una r<strong>el</strong>ación simple, la solución óptima se obtiene evaluando <strong>el</strong> costo<br />

<strong>para</strong> cada camino <strong>de</strong> acceso (cada índice en la r<strong>el</strong>ación más un “segment scan”).<br />

Si no hay cláusulas GROUP BY u ORDER BY en la consulta no hay “interesting<br />

or<strong>de</strong>rs”, por lo tanto se <strong>de</strong>berá <strong>el</strong>egir <strong>el</strong> camino <strong>de</strong> acceso más barato. Si estas<br />

sentencias existen, se necesita examinar los caminos <strong>de</strong> acceso más baratos que<br />

produzcan tuplas en cada uno <strong>de</strong> los “insteresting or<strong>de</strong>rs”, luego, <strong>el</strong> costo <strong>de</strong><br />

producir estos or<strong>de</strong>namientos <strong>de</strong>be com<strong>para</strong>rse al costo <strong>de</strong>l más barato <strong>de</strong> los<br />

caminos “sin or<strong>de</strong>n” más <strong>el</strong> costo <strong>de</strong> or<strong>de</strong>nar las QCARDS tuplas <strong>de</strong> la consulta<br />

en <strong>el</strong> or<strong>de</strong>n dado. La más barata <strong>de</strong> estas alternativas será la <strong>el</strong>egida como <strong>el</strong> plan<br />

<strong>de</strong> ejecución <strong>para</strong> <strong>el</strong> bloque.<br />

La siguiente tabla muestra las fórmulas <strong>de</strong> costo <strong>para</strong> caminos <strong>de</strong> acceso a<br />

r<strong>el</strong>aciones simples. Estas fórmulas se calculan basándose en la suma <strong>de</strong>l número<br />

<strong>de</strong> páginas <strong>de</strong> índices y las paginas <strong>de</strong> datos más <strong>el</strong> factor <strong>de</strong> peso multiplicado<br />

por las “RSI call”. En algunos casos se dan varias alternativas <strong>de</strong>pendiendo <strong>de</strong> si<br />

<strong>el</strong> conjunto <strong>de</strong> tuplas rescatadas “cabe” completamente en <strong>el</strong> RSS buffer pool.<br />

Para índices en cluster se asume que una página permanecerá en <strong>el</strong> buffer lo<br />

suficiente como <strong>para</strong> que todas las tuplas puedan ser rescatadas <strong>de</strong> <strong>el</strong>la. Para<br />

índices que no son en cluster y en <strong>el</strong> caso <strong>de</strong> aqu<strong>el</strong>las r<strong>el</strong>aciones que no caben en<br />

59


<strong>el</strong> buffer, se asume que la r<strong>el</strong>ación es suficientemente gran<strong>de</strong> con respecto al<br />

buffer <strong>de</strong> manera que se requiere una lectura <strong>de</strong> página por cada tupla rescatada.<br />

Situación<br />

Indice único que calza con<br />

un predicado <strong>de</strong> igualdad<br />

Indice en cluster I que<br />

calza con uno o más<br />

factores booleanos<br />

Indice I que calza uno o<br />

más factores boléanos<br />

Indice en cluster I que no<br />

calza con ningún factor<br />

booleano<br />

Indice I que no calza con<br />

ningún factor booleano<br />

Costo<br />

1 + 1 + W<br />

F(preds) * (NINDX(I) + TCARD) + W * RSICARD<br />

60<br />

F(preds) * (NINDX(I) + NCARD) + W * RSICARD<br />

o<br />

F(preds) * (NINDX(I) + TCARD) + W * RSICARD<br />

si este número cabe en <strong>el</strong> buffer <strong>de</strong> System R<br />

(NINDX(I) + TCARD) + W * RSICARD<br />

(NINDX(I) + NCARD) + W * RSICARD<br />

o<br />

(NINDX(I) + TCARD) + W * RSICARD si este<br />

número cabe en <strong>el</strong> buffer <strong>de</strong> System R


Segment Scan<br />

TCARD/P + W * RSICARD<br />

Tabla 4-2 - Fórmulas <strong>de</strong> costo <strong>para</strong> caminos <strong>de</strong> acceso a r<strong>el</strong>aciones simples<br />

4.2.3. S<strong>el</strong>ección <strong>de</strong>l camino <strong>de</strong> acceso <strong>para</strong> joins.<br />

El optimizador <strong>de</strong> system R tiene 2 métodos <strong>de</strong> s<strong>el</strong>ección <strong>de</strong> caminos <strong>de</strong><br />

acceso <strong>para</strong> los joins <strong>de</strong> dos r<strong>el</strong>aciones (join <strong>de</strong> or<strong>de</strong>n 2), primero se <strong>de</strong>scribirán<br />

estos métodos y luego se discutirá como <strong>el</strong>los pue<strong>de</strong>n ser extendidos <strong>para</strong> joins<br />

con más <strong>de</strong> 2 r<strong>el</strong>aciones (join <strong>de</strong> or<strong>de</strong>n n). Para <strong>el</strong> primer caso, la r<strong>el</strong>ación base<br />

recibirá <strong>el</strong> nombre <strong>de</strong> r<strong>el</strong>ación outer, la segunda r<strong>el</strong>ación se le llamará inner y<br />

correspon<strong>de</strong>rá a la r<strong>el</strong>ación <strong>de</strong> la cual se sacarán las tuplas <strong>de</strong>pendiendo <strong>de</strong> los<br />

valores obtenidos <strong>de</strong> la r<strong>el</strong>ación outer. Un predicado que r<strong>el</strong>aciona columnas <strong>de</strong> 2<br />

r<strong>el</strong>aciones <strong>de</strong> un join se llamará un predicado <strong>de</strong> join, las columnas referenciadas<br />

en estos predicados se llamaran columnas <strong>de</strong> join.<br />

El primer método se llama nested loops (ciclos anidados) y consiste en<br />

recorrer ambas r<strong>el</strong>aciones en cualquier or<strong>de</strong>n. Primero se abre un scan sobre la<br />

r<strong>el</strong>ación outer y se rescata la primera tupla, <strong>para</strong> cada tupla <strong>de</strong> esta r<strong>el</strong>ación se<br />

abre un “segment scan” en la r<strong>el</strong>ación inner <strong>para</strong> rescatar, una a la vez, las tuplas<br />

que coinci<strong>de</strong>n con <strong>el</strong> predicado <strong>de</strong> join.<br />

El segundo método se llama merging scans (recorrido por mezcla), requiere<br />

que las dos r<strong>el</strong>aciones se recorran en <strong>el</strong> or<strong>de</strong>n <strong>de</strong> las columnas <strong>de</strong> join. Esto<br />

implica que, junto con las columnas mencionadas en las cláusulas ORDER BY y<br />

GROUP BY, las columnas <strong>de</strong> un predicado equi-join (aqu<strong>el</strong>los <strong>de</strong> la forma<br />

tabla1.columna1 = tabla2.columna2) también <strong>de</strong>finen “interesting or<strong>de</strong>rs”.<br />

Si hay más <strong>de</strong> un predicado <strong>de</strong> join, uno <strong>de</strong> <strong>el</strong>los es usado como predicado <strong>de</strong> join<br />

y los restantes son tratados como predicados ordinarios. Este método solamente<br />

61


se aplica a equi-joins, si una o ambas r<strong>el</strong>aciones <strong>de</strong>l join no tienen índices en las<br />

columnas <strong>de</strong> join, estas <strong>de</strong>ben ser or<strong>de</strong>nadas en una lista temporal por las<br />

columnas <strong>de</strong> join.<br />

Este método saca provecho <strong>de</strong>l or<strong>de</strong>namiento <strong>de</strong> las columnas <strong>de</strong> join<br />

evitando recorrer la r<strong>el</strong>ación inner por cada tupla <strong>de</strong> la r<strong>el</strong>ación outer. Esto se hace<br />

sincronizando ambos scans y recordando don<strong>de</strong> se encuentran las tuplas que<br />

satisfacen <strong>el</strong> predicado <strong>de</strong> join. Un mayor ahorro <strong>de</strong> esfuerzos se logra si la<br />

r<strong>el</strong>ación inner está en cluster sobre la columna <strong>de</strong> join (como <strong>de</strong>bería si esta fuese<br />

la salida <strong>de</strong> un sort sobre la columna <strong>de</strong> join). “Clustering” sobre una columna<br />

significa que las tuplas que tienen <strong>el</strong> mismo valor en esta columna están<br />

almacenadas físicamente cerca una <strong>de</strong> la otra <strong>de</strong> manera que <strong>el</strong> acceso a una<br />

página traiga varias tuplas.<br />

Un “join <strong>de</strong> or<strong>de</strong>n n” se pue<strong>de</strong> visualizar como una secuencia <strong>de</strong> joins <strong>de</strong><br />

or<strong>de</strong>n 2. En esta visualización 2 r<strong>el</strong>aciones formarán un join, <strong>el</strong> resultado <strong>de</strong> estos<br />

se cruzara con una tercera r<strong>el</strong>ación <strong>para</strong> formar <strong>el</strong> segundo join y así<br />

sucesivamente. En cada paso es posible i<strong>de</strong>ntificar la r<strong>el</strong>ación outer (la que<br />

generalmente es la composición <strong>de</strong>l paso anterior) y la r<strong>el</strong>ación inner como la<br />

r<strong>el</strong>ación que está siendo agregada al join. Es importante notar que no es necesario<br />

que termine <strong>el</strong> primer join <strong>para</strong> que empiece <strong>el</strong> segundo. Tan pronto como se<br />

tenga una tupla producto <strong>de</strong>l primer join <strong>de</strong> or<strong>de</strong>n 2, esta pue<strong>de</strong> ser cruzada con<br />

tuplas <strong>de</strong> la tercera r<strong>el</strong>ación con <strong>el</strong> fin <strong>de</strong> obtener tuplas que sirven <strong>para</strong> <strong>el</strong> tercer<br />

join y así sucesivamente.<br />

Otro factor a consi<strong>de</strong>rar en un join es <strong>el</strong> or<strong>de</strong>n en que se escogen las<br />

r<strong>el</strong>aciones. Aunque la cardinalidad <strong>de</strong> una consulta <strong>de</strong> n r<strong>el</strong>aciones sea la misma<br />

indiferente <strong>de</strong>l or<strong>de</strong>n <strong>de</strong> <strong>el</strong>ección, <strong>el</strong> costo <strong>de</strong> cruzarlas en distinto or<strong>de</strong>n pue<strong>de</strong> ser<br />

substancialmente diferente. Si un bloque tiene n r<strong>el</strong>aciones en su lista FROM<br />

entonces existe n! (n factorial) formas <strong>de</strong> permutar <strong>el</strong> or<strong>de</strong>n <strong>de</strong> las r<strong>el</strong>aciones (la<br />

62


explicación <strong>de</strong> esto se pue<strong>de</strong> encontrar más a<strong>de</strong>lante, en la sección 5.5). Una vez<br />

que las primeras k r<strong>el</strong>aciones han sido unidas, <strong>el</strong> método <strong>para</strong> cruzar esta<br />

composición con la k+1 ésima r<strong>el</strong>ación es in<strong>de</strong>pendiente <strong>de</strong>l or<strong>de</strong>n en que se<br />

unieron las k anteriores. Usando esta propiedad, una forma eficiente <strong>de</strong> organizar<br />

la búsqueda es encontrar <strong>el</strong> mejor or<strong>de</strong>namiento <strong>para</strong> conjuntos sucesivamente<br />

más gran<strong>de</strong>s.<br />

La heurística que se utiliza <strong>para</strong> reducir <strong>el</strong> número <strong>de</strong> permutaciones es<br />

consi<strong>de</strong>rar sólo los or<strong>de</strong>namientos los cuales tienen predicados <strong>de</strong> join que<br />

r<strong>el</strong>acionan la r<strong>el</strong>ación inner con <strong>el</strong> resto <strong>de</strong> las r<strong>el</strong>aciones que participan en <strong>el</strong> join.<br />

Esta heurística permite que todos los joins que requieran productos cartesianos se<br />

realicen lo más tar<strong>de</strong> posible. Por ejemplo, si T1, T2 y T3 son las 3 r<strong>el</strong>aciones <strong>de</strong><br />

una lista FROM y hay predicados <strong>de</strong> join entre T1 T2, y entre T2 y T3 pero sobre<br />

columnas distintas, entonces las permutaciones siguientes no serán consi<strong>de</strong>radas.<br />

T1 – T3 – T2<br />

T3 – T1 – T2<br />

Para encontrar <strong>el</strong> plan óptimo <strong>para</strong> un join <strong>de</strong> or<strong>de</strong>n n se construye un árbol<br />

<strong>de</strong> posibles soluciones. Una solución consiste en una lista or<strong>de</strong>nada <strong>de</strong> r<strong>el</strong>aciones<br />

a ser unidas, <strong>el</strong> método <strong>de</strong> join y un plan que indique como se accesa cada<br />

r<strong>el</strong>ación. Si una <strong>de</strong> las dos r<strong>el</strong>aciones necesita ser or<strong>de</strong>nada antes <strong>de</strong>l join,<br />

entonces se guarda <strong>el</strong> costo <strong>de</strong> este or<strong>de</strong>namiento en <strong>el</strong> plan. Para minimizar la<br />

cantidad <strong>de</strong> “interesting or<strong>de</strong>rs” y con esto también <strong>el</strong> número <strong>de</strong> soluciones, se<br />

calcularán clases <strong>de</strong> equivalencia <strong>para</strong> los “interesting or<strong>de</strong>rs”, y sólo la mejor<br />

solución <strong>de</strong> cada una <strong>de</strong> las clases <strong>de</strong> equivalencia será guardada en <strong>el</strong> árbol.<br />

El árbol <strong>de</strong> búsqueda se construye por medio <strong>de</strong> la iteración <strong>de</strong> las<br />

r<strong>el</strong>aciones que han sido juntadas hasta <strong>el</strong> momento. Primero, se encuentra la<br />

mejor manera <strong>de</strong> accesar a cada r<strong>el</strong>ación simple <strong>para</strong> cada “interesting or<strong>de</strong>r” y<br />

63


<strong>para</strong> <strong>el</strong> caso sin or<strong>de</strong>n. Luego <strong>para</strong> cada una <strong>de</strong> las r<strong>el</strong>aciones se <strong>el</strong>ige la mejor<br />

manera <strong>de</strong> juntar otra r<strong>el</strong>ación a esta (sujeta a las heurísticas <strong>para</strong> <strong>el</strong><br />

or<strong>de</strong>namiento <strong>de</strong> join), esto produce soluciones <strong>para</strong> juntar pares <strong>de</strong> r<strong>el</strong>aciones.<br />

Luego se <strong>el</strong>ige la mejor manera <strong>de</strong> juntar conjuntos <strong>de</strong> 3 r<strong>el</strong>aciones, consi<strong>de</strong>rando<br />

todos los conjuntos <strong>de</strong> 2 r<strong>el</strong>aciones y agregándole una tercera r<strong>el</strong>ación<br />

consi<strong>de</strong>rando las heurísticas <strong>para</strong> <strong>el</strong> or<strong>de</strong>namiento <strong>de</strong> joins. Para cada plan que<br />

juntará un conjunto <strong>de</strong> r<strong>el</strong>aciones se guarda en <strong>el</strong> árbol <strong>el</strong> or<strong>de</strong>n <strong>de</strong> la<br />

composición. Esto ayuda a la consi<strong>de</strong>ración <strong>de</strong> usar un “merge join” que<br />

eventualmente no requiera or<strong>de</strong>namiento adicional <strong>de</strong> tuplas. Luego <strong>de</strong> que se<br />

tienen todas las posibles soluciones, <strong>el</strong> optimizador <strong>el</strong>ige la solución más barata<br />

que da <strong>el</strong> or<strong>de</strong>n requerido (si se ha especificado algún or<strong>de</strong>n). Nótese que si existe<br />

una solución con <strong>el</strong> or<strong>de</strong>n correcto, no se necesitará efectuar un sort <strong>para</strong><br />

satisfacer las cláusulas ORDER BY o GROUP BY, a menos que la solución<br />

or<strong>de</strong>nada sea más costosa que la más barata <strong>de</strong> las sin or<strong>de</strong>n más <strong>el</strong> costo <strong>de</strong><br />

or<strong>de</strong>narlas en <strong>el</strong> or<strong>de</strong>n requerido.<br />

4.2.4. Cálculo <strong>de</strong> costos <strong>para</strong> joins.<br />

El costo <strong>para</strong> un join se calcula dado <strong>el</strong> costo <strong>de</strong> los scans en cada una <strong>de</strong><br />

las r<strong>el</strong>aciones que participan y las respectivas cardinalida<strong>de</strong>s. El costo <strong>de</strong> un scan<br />

en las r<strong>el</strong>aciones participantes se calcula con la fórmula <strong>de</strong> costo <strong>de</strong> r<strong>el</strong>aciones<br />

simples expuestas en <strong>el</strong> punto 4.2.2.<br />

Sea C-outer(path1) <strong>el</strong> costo <strong>de</strong> recorrer la r<strong>el</strong>ación outer vía path1. Sea N la<br />

cardinalidad <strong>de</strong> tuplas que satisfacen los predicados <strong>de</strong> la r<strong>el</strong>ación outer. N se<br />

calcula como:<br />

N = (producto <strong>de</strong> las cardinalida<strong>de</strong>s <strong>de</strong> todas las r<strong>el</strong>aciones T incluidas<br />

hasta <strong>el</strong> momento).<br />

64


Sea C-inner(path2) <strong>el</strong> costo <strong>de</strong> recorrer la r<strong>el</strong>ación inner aplicando todos los<br />

predicados aplicables. Sea <strong>el</strong> costo <strong>de</strong> un “join nested loop”:<br />

c-nested-loop-join(path1, path2) = C-outer(path1) + N * C-inner(path2)<br />

El costo <strong>de</strong> un merge join se pue<strong>de</strong> se<strong>para</strong>r en <strong>el</strong> costo <strong>de</strong> hacer <strong>el</strong> join más<br />

<strong>el</strong> costo <strong>de</strong>l or<strong>de</strong>namiento en cada una <strong>de</strong> las r<strong>el</strong>aciones si fuese necesario. El<br />

costo <strong>de</strong> efectuar <strong>el</strong> merge join es:<br />

c-merge-join(path1, path2) = C-outer(path1) + N * C-inner(path2)<br />

Para <strong>el</strong> caso en que la r<strong>el</strong>ación inner es or<strong>de</strong>nada en una r<strong>el</strong>ación temporal<br />

no se aplica ninguna <strong>de</strong> las fórmulas dadas <strong>para</strong> caminos <strong>de</strong> acceso a r<strong>el</strong>aciones<br />

simples. En este caso <strong>el</strong> inner scan es como un “segment scan” a excepción <strong>de</strong><br />

que <strong>el</strong> método <strong>de</strong> “merging scan” hace uso <strong>de</strong>l hecho <strong>de</strong> que la r<strong>el</strong>ación inner está<br />

or<strong>de</strong>nada, por lo tanto no es necesario realizar un scan a toda la r<strong>el</strong>ación<br />

buscando una coinci<strong>de</strong>ncia. Para este caso se utilizará la siguiente formula <strong>para</strong> <strong>el</strong><br />

costo <strong>de</strong> un “inner scan”:<br />

C-inner(sorted list) = TEMPPAGES / N + W * RSICARD<br />

Don<strong>de</strong> TEMPAGES es <strong>el</strong> número <strong>de</strong> paginas que se requieren <strong>para</strong><br />

mantener la r<strong>el</strong>ación inner. Esta formula asume que durante <strong>el</strong> “merge scan” cada<br />

página <strong>de</strong> la r<strong>el</strong>ación inner se rescata una vez.<br />

Es interesante observar que las formulas <strong>de</strong> costo <strong>para</strong> <strong>el</strong> “nested-loop-join”<br />

y “merge-join” son esencialmente las mismas, la razón <strong>de</strong> porque algunas veces <strong>el</strong><br />

“merge-join” pue<strong>de</strong> ser más eficiente es que <strong>el</strong> costo <strong>de</strong>l inner scan pue<strong>de</strong> ser<br />

mucho más bajo. Una vez or<strong>de</strong>nada, la r<strong>el</strong>ación inner está en cluster sobre la<br />

65


columna <strong>de</strong> join lo que minimiza <strong>el</strong> número <strong>de</strong> paginas rescatadas y, por lo tanto,<br />

no es necesario hacer un scan sobre toda la r<strong>el</strong>ación con fin <strong>el</strong> <strong>de</strong> obtener una<br />

coinci<strong>de</strong>ncia.<br />

4.2.5. Costos <strong>de</strong> <strong>consultas</strong> anidadas.<br />

Una consulta pue<strong>de</strong> aparecer como operando <strong>de</strong> un predicado <strong>de</strong> la forma<br />

“expresión operando consulta”, tal consulta es llamada consulta anidada o<br />

subconsulta. Si <strong>el</strong> operador es uno <strong>de</strong> los cinco operadores escalares ( =, >, >=,


<strong>consultas</strong> son llamadas sub<strong>consultas</strong> corr<strong>el</strong>acionadas. Una consulta<br />

corr<strong>el</strong>acionada <strong>de</strong>be, en principio ser re-evaluada <strong>para</strong> cada tupla candidata <strong>de</strong>l<br />

bloque referenciado. Esta re-evaluación <strong>de</strong>be ser hecha antes <strong>de</strong> que <strong>el</strong> predicado<br />

padre <strong>de</strong> la consulta corr<strong>el</strong>acionada pueda ser testeado <strong>para</strong> aceptación o rechazo<br />

<strong>de</strong> la tupla candidata. Como ejemplo considérese la siguiente consulta:<br />

SELECT NAME<br />

FROM EMPLOYEE X<br />

WHERE SALARY > (SELECT SALARY<br />

FROM EMPLOYEE<br />

WHERE EMPLOYEE_NUMBER = X.MANAGER)<br />

Esta consulta s<strong>el</strong>ecciona los nombres <strong>de</strong> empleados que ganan más que<br />

sus Jefes. Aquí X i<strong>de</strong>ntifica <strong>el</strong> bloque y la r<strong>el</strong>ación que proporciona tuplas<br />

candidatas <strong>para</strong> la corr<strong>el</strong>ación. Para cada tupla candidata <strong>de</strong> la consulta <strong>de</strong> primer<br />

niv<strong>el</strong>, se utilizará <strong>el</strong> valor <strong>de</strong> MANAGER <strong>para</strong> la evaluación <strong>de</strong> la subconsulta, <strong>el</strong><br />

valor <strong>de</strong> la subconsulta se le retorna al predicado “SALARY >” con <strong>el</strong> fin <strong>de</strong> aceptar<br />

o rechazar la tupla candidata.<br />

Si una subconsulta <strong>de</strong> corr<strong>el</strong>ación no está directamente <strong>de</strong>bajo <strong>de</strong>l bloque<br />

que referencia, sino que está se<strong>para</strong>da por medio <strong>de</strong> uno o más bloques, entonces<br />

la evaluación <strong>de</strong> la subconsulta <strong>de</strong> corr<strong>el</strong>ación <strong>de</strong>be ser hecha antes <strong>de</strong> la<br />

evaluación <strong>de</strong>l más alto <strong>de</strong> los bloques intermedios.<br />

Por ejemplo:<br />

67


Niv<strong>el</strong> 1 SELECT NAME<br />

FROM EMPLOYEE X<br />

WHERE SALARY > (<br />

Niv<strong>el</strong> 2 SELECT SALARY<br />

FROM EMPLOYEE<br />

WHERE EMPLOYEE_NUMBER = (<br />

Niv<strong>el</strong> 3 SELECT MANAGER<br />

FROM EMPLOYEE<br />

WHERE EMPLOYEE_NUMBER = X.MANAGER))<br />

Esta consulta s<strong>el</strong>ecciona los nombres <strong>de</strong> los empleados que ganan más<br />

que los Jefes <strong>de</strong> sus Jefes. Como antes se vio, <strong>para</strong> cada tupla candidata <strong>de</strong>l<br />

bloque <strong>de</strong> niv<strong>el</strong> 1 <strong>el</strong> valor <strong>de</strong> EMPLOYEE.MANAGER se usará <strong>para</strong> la evaluación<br />

<strong>de</strong>l bloque <strong>de</strong> niv<strong>el</strong> 3. En este caso, dado que la subconsulta <strong>de</strong> niv<strong>el</strong> 3 referencia<br />

a una valor <strong>de</strong> niv<strong>el</strong> 1 pero no referencia a valores <strong>de</strong> niv<strong>el</strong> 2, esta es evaluada<br />

una vez <strong>para</strong> cada tupla candidata <strong>de</strong> niv<strong>el</strong> 1 pero no <strong>para</strong> las tuplas candidatas <strong>de</strong><br />

niv<strong>el</strong> 2.<br />

Si <strong>el</strong> valor referenciado por la subconsulta <strong>de</strong> corr<strong>el</strong>ación no es único en <strong>el</strong><br />

conjunto <strong>de</strong> tuplas candidatas entonces este procedimiento causará que la<br />

consulta sea re-evaluada <strong>para</strong> cada ocurrencia <strong>de</strong> los valores repetidos. Sin<br />

embargo si la r<strong>el</strong>ación a la que se hace referencia está or<strong>de</strong>nada por la columna<br />

referenciada la re-evaluación pue<strong>de</strong> ser condicional, y <strong>de</strong>pen<strong>de</strong>rá <strong>de</strong> saber si <strong>el</strong><br />

valor actual es <strong>el</strong> mismo que <strong>el</strong> <strong>de</strong> la tupla candidata procesada anteriormente. Si<br />

son iguales entonces se pue<strong>de</strong> utilizar la evaluación anterior, en algunos casos<br />

incluso se pue<strong>de</strong> or<strong>de</strong>nar la r<strong>el</strong>ación por la columna referenciada con <strong>el</strong> fin <strong>de</strong><br />

evitar la innecesaria re-evaluación <strong>de</strong> sub<strong>consultas</strong>. Con <strong>el</strong> fin <strong>de</strong> <strong>de</strong>terminar si los<br />

valores <strong>de</strong> una columna referenciada son únicos se pue<strong>de</strong>n utilizar pistas como<br />

NCARD > ICARD, don<strong>de</strong> NCARD es la cardinalidad <strong>de</strong> la r<strong>el</strong>ación y ICARD es la<br />

cardinalidad <strong>de</strong>l índice sobre la columna referenciada.<br />

68


Capítulo 5. Optimización <strong>de</strong> <strong>consultas</strong>, Fundamento<br />

teórico.<br />

5.1. Introducción.<br />

En Los mo<strong>de</strong>los <strong>de</strong> Red y Jerárquico la optimización <strong>de</strong> <strong>consultas</strong> es tarea<br />

propia <strong>de</strong>l programador <strong>de</strong> aplicaciones, puesto que las instrucciones <strong>de</strong><br />

manipulación <strong>de</strong> datos son propietarias <strong>de</strong>l <strong>lenguaje</strong> anfitrión. Por <strong>el</strong> contrario las<br />

<strong>consultas</strong> <strong>de</strong> base <strong>de</strong> datos r<strong>el</strong>acionales son o bien <strong>de</strong>clarativas o algebraicas. Los<br />

<strong>lenguaje</strong>s algebraicos permiten la transformación algebraica <strong>de</strong> la consulta, luego,<br />

basándose en la especificación algebraica <strong>de</strong> la consulta es r<strong>el</strong>ativamente fácil<br />

<strong>para</strong> <strong>el</strong> optimizador generar diversos planes equivalentes <strong>para</strong> la consulta y <strong>el</strong>egir<br />

<strong>el</strong> menos costoso.<br />

Dado este niv<strong>el</strong> <strong>de</strong> generalidad, <strong>el</strong> optimizador pue<strong>de</strong> ser visto como <strong>el</strong><br />

generador <strong>de</strong> código <strong>de</strong> un compilador <strong>para</strong> <strong>el</strong> <strong>lenguaje</strong> SQL, que produce <strong>el</strong><br />

código que será interpretado por <strong>el</strong> motor <strong>de</strong> ejecución <strong>de</strong> <strong>consultas</strong>, excepto que<br />

<strong>el</strong> optimizador marca énfasis en la capacidad <strong>de</strong> producir <strong>el</strong> código más eficiente,<br />

haciendo uso <strong>para</strong> tales efectos <strong>de</strong>l catálogo <strong>de</strong> la base <strong>de</strong> datos, <strong>de</strong> don<strong>de</strong><br />

obtiene información estadística <strong>de</strong> las r<strong>el</strong>aciones referenciadas por la consulta,<br />

algo que los <strong>lenguaje</strong>s <strong>de</strong> programación tradicionales no hacen.<br />

Un aspecto <strong>de</strong> la optimización <strong>de</strong> <strong>consultas</strong> se sitúa en <strong>el</strong> niv<strong>el</strong> <strong>de</strong>l álgebra<br />

r<strong>el</strong>acional. Dado un conjunto <strong>de</strong> reglas se trata <strong>de</strong> encontrar una expresión que<br />

sea equivalente a la expresión dada pero que sea más eficiente en la ejecución.<br />

69


Con <strong>el</strong> fin <strong>de</strong> s<strong>el</strong>eccionar la mejor estrategia <strong>para</strong> la recuperación <strong>de</strong> datos<br />

<strong>el</strong> optimizador “estima” un costo que estará r<strong>el</strong>acionado a cada plan <strong>de</strong> ejecución.<br />

Este costo está <strong>de</strong>terminado por fórmulas pre<strong>de</strong>finidas en base a información que<br />

se posee <strong>de</strong> la tabla y que se ha rescatado previamente <strong>de</strong>l catálogo <strong>de</strong> la base <strong>de</strong><br />

datos, en realidad <strong>el</strong> optimizador no siempre escoge <strong>el</strong> plan más óptimo, ya que<br />

encontrar la estrategia óptima pue<strong>de</strong> consumir mucho tiempo, por lo tanto se dice<br />

que <strong>el</strong> optimizador “sólo escoge una estrategia razonablemente eficiente”. La<br />

manera con la que <strong>el</strong> optimizador utiliza esa información, las distintas técnicas y<br />

algoritmos que aplica y las transformaciones algebraicas que se realizan son las<br />

que diferencian a los optimizadores <strong>de</strong> bases <strong>de</strong> datos.<br />

Un optimizador basado en <strong>el</strong> costo genera una serie <strong>de</strong> planes <strong>de</strong><br />

evaluación <strong>para</strong> una consulta y luego <strong>el</strong>ige <strong>el</strong> que tiene un menor costo asociado,<br />

las medidas <strong>de</strong> costo comúnmente tienen que ver con la E/S y <strong>el</strong> tiempo <strong>de</strong> CPU<br />

utilizado en ejecutar la consulta, sin embargo, es cuestión <strong>de</strong> cada SGBD <strong>el</strong> <strong>el</strong>egir<br />

las medidas <strong>de</strong> costo que mejor representen <strong>el</strong> criterio <strong>de</strong> minimización en la<br />

utilización <strong>de</strong> recursos.<br />

5.2. Información <strong>de</strong>l catálogo.<br />

Como se ha mencionado anteriormente, la información <strong>de</strong>l catálogo <strong>de</strong> la<br />

base <strong>de</strong> datos le sirve al SGBD <strong>para</strong> estimar <strong>el</strong> costo <strong>de</strong> los planes <strong>de</strong> ejecución<br />

<strong>de</strong> una consulta. La precisión <strong>de</strong> esta información esta ligada directamente a la<br />

periodicidad con la que se actualizan las estadísticas <strong>de</strong>l catálogo. En un caso<br />

i<strong>de</strong>al, cada vez que se compromete una transacción <strong>de</strong> base <strong>de</strong> datos se <strong>de</strong>berían<br />

actualizar las estadísticas <strong>de</strong>l sistema, sin embargo, esto no es posible en un<br />

70


entorno OLTP 13 dada la sobrecarga que estas operaciones le dan al sistema<br />

(básicamente bloqueos en las tablas <strong>de</strong>l catálogo). La solución está entonces en la<br />

posibilidad <strong>de</strong> actualizar estas estadísticas en periodo <strong>de</strong> poca carga <strong>de</strong>l sistema,<br />

algunos SGBD tienen técnicas <strong>de</strong> optimización automáticas <strong>de</strong> las estadísticas<br />

(como es <strong>el</strong> caso <strong>de</strong> MS-SQLServer [Bj<strong>el</strong>etich99]) pero en general se recomienda<br />

que esta tarea la ejecute <strong>el</strong> DBA con la periodicidad que le dicte la experiencia. En<br />

todo caso, la información será más precisa cuanto más bajo sea <strong>el</strong> niv<strong>el</strong> <strong>de</strong><br />

actualizaciones en <strong>el</strong> intervalo <strong>de</strong> tiempo entre actualizaciones <strong>de</strong> Estadísticas.<br />

Cada SGBD tiene distinta información que guardar en <strong>el</strong> catálogo y por<br />

en<strong>de</strong>, <strong>el</strong> catálogo <strong>de</strong> la base <strong>de</strong> datos es distinto entre cada uno <strong>de</strong> estos motores,<br />

sin embargo, hay información que todo optimizador <strong>de</strong>be guardar:<br />

n r Número <strong>de</strong> tuplas <strong>de</strong> la r<strong>el</strong>ación r<br />

b r Número <strong>de</strong> bloques que contienen tuplas <strong>de</strong> la r<strong>el</strong>ación r<br />

t r Tamaño en bytes <strong>de</strong> una tupla <strong>de</strong> r<br />

f r Factor <strong>de</strong> bloqueo <strong>de</strong> r. Número <strong>de</strong> tuplas <strong>de</strong> r que caben en un bloque.<br />

V ( A,<br />

r)<br />

Número <strong>de</strong> valores distintos <strong>de</strong>l atributo A <strong>de</strong> la r<strong>el</strong>ación r<br />

CS ( A,<br />

r)<br />

Número medio <strong>de</strong> tuplas <strong>de</strong> r que satisfacen una condición <strong>de</strong> igualdad<br />

sobre <strong>el</strong> atributo A <strong>de</strong> la r<strong>el</strong>ación r<br />

CS ( A,<br />

r)<br />

= 1 Si A es clave <strong>de</strong> r<br />

nr<br />

CS(<br />

A,<br />

r)<br />

=<br />

V ( A,<br />

r)<br />

Si A no es clave <strong>de</strong> r, se asume una distribución<br />

71<br />

uniforme <strong>de</strong> los datos <strong>de</strong> A sobre r<br />

Tabla 5-1 - Información <strong>de</strong>l Catálogo <strong>para</strong> r<strong>el</strong>aciones simples.<br />

13 On Line Transaction Processing: tipo <strong>de</strong> procesamiento en <strong>el</strong> cual <strong>el</strong> computador<br />

respon<strong>de</strong> los requerimientos <strong>de</strong> usuario inmediatamente, cada requerimiento es consi<strong>de</strong>rado una<br />

transacción. Un ejemplo <strong>de</strong> este tipo <strong>de</strong> procesamiento es <strong>el</strong> <strong>de</strong> los cajeros automáticos.


Por ejemplo, si n r = 10 y V(sexo,r) = 2 entonces CS(sexo,r) = 10 / 2 = 5, se<br />

asume por lo tanto que <strong>el</strong> atributo sexo se distribuye homogéneamente sobre r.<br />

n r ⎡n<br />

⎤ r<br />

Se asume a<strong>de</strong>más que si = f r entonces b r = ⎢ ⎥<br />

br<br />

⎢ f r ⎥<br />

A<strong>de</strong>más <strong>de</strong> la información <strong>de</strong>l catálogo <strong>para</strong> las r<strong>el</strong>aciones, se utiliza<br />

información acerca <strong>de</strong> los índices:<br />

g Grado <strong>de</strong> salida <strong>de</strong> los nodos internos <strong>de</strong>l índice i (<strong>para</strong> índices con<br />

i<br />

estructura <strong>de</strong> Arbol B+)<br />

AA i<br />

Altura <strong>de</strong>l índice <strong>para</strong> <strong>el</strong> atributo A <strong>de</strong> r.<br />

AAi =<br />

i<br />

⎡log f ( V ( A,<br />

r))<br />

⎤<br />

MB Número <strong>de</strong> bloques que ocupa <strong>el</strong> niv<strong>el</strong> más bajo (niv<strong>el</strong> <strong>de</strong> hojas) <strong>de</strong>l índice i<br />

i<br />

5.3. Medidas <strong>de</strong> costo.<br />

Tabla 5-2 - Información <strong>de</strong>l catálogo <strong>para</strong> índices <strong>de</strong> R<strong>el</strong>aciones.<br />

El costo <strong>de</strong> un plan <strong>de</strong> ejecución se pue<strong>de</strong> expresar en términos <strong>de</strong> distintos<br />

recursos <strong>de</strong> hardware, por ejemplo, en <strong>el</strong> caso <strong>de</strong> system R se hace en función <strong>de</strong><br />

la cantidad <strong>de</strong> CPU utilizada y <strong>de</strong> la cantidad <strong>de</strong> páginas <strong>de</strong> disco rescatadas. En<br />

los SGBD distribuidos se agrega a las medidas <strong>el</strong> costo <strong>de</strong> la comunicación <strong>de</strong><br />

re<strong>de</strong>s. En los sistemas que no son centralizados conviene creer que una buena<br />

medida <strong>de</strong>l costo <strong>de</strong> utilización <strong>de</strong> recursos es la que está dada por la<br />

transferencia <strong>de</strong> datos <strong>de</strong>s<strong>de</strong> <strong>el</strong> disco a la memoria. Para simplificar los cálculos<br />

<strong>de</strong> costo se asume que toda operación que recupere datos <strong>de</strong> disco tiene <strong>el</strong><br />

mismo costo, obviando, por simplicidad, los tiempos involucrados en latencia<br />

rotacional y <strong>el</strong> tiempo <strong>de</strong> búsqueda (ver apéndice C apartado C.1.1) .<br />

72


El costo <strong>de</strong> todos los algoritmos <strong>de</strong> optimización <strong>de</strong>pen<strong>de</strong> en gran manera<br />

<strong>de</strong>l tamaño <strong>de</strong> la memoria intermedia (caché) que tenga la memoria principal. En<br />

<strong>el</strong> mejor <strong>de</strong> los casos todos los datos requeridos se encuentran en la memoria<br />

principal por lo que no se hace necesario acce<strong>de</strong>r al disco.<br />

Al igual que en <strong>el</strong> caso <strong>de</strong>l optimizador <strong>de</strong> system R, este trabajo presenta<br />

los algoritmos <strong>de</strong> optimización consi<strong>de</strong>rando <strong>el</strong> peor caso, en <strong>el</strong> cual sólo algunos<br />

datos caben en la memoria principal, más bien dicho, sólo un bloque por r<strong>el</strong>ación.<br />

5.3.1. Caminos <strong>de</strong> acceso a s<strong>el</strong>ecciones simples.<br />

5.3.1.1. Exploraciones sin índices.<br />

Los siguientes algoritmos implementan la operación <strong>de</strong> s<strong>el</strong>ección sobre una<br />

r<strong>el</strong>ación cuyas tuplas están almacenadas <strong>de</strong> manera contigua en un archivo 14 .<br />

A1. Búsqueda lineal (Full scan o table scan): Se examina cada bloque <strong>de</strong>l<br />

archivo y se comprueba si los registros cumplen con la condición <strong>de</strong> s<strong>el</strong>ección. El<br />

costo estimado <strong>de</strong> este algoritmo es :<br />

C = b<br />

A2. Búsqueda binaria: Si la tabla esta or<strong>de</strong>nada físicamente por <strong>el</strong> atributo A y la<br />

condición <strong>de</strong> s<strong>el</strong>ección es una igualdad sobre <strong>el</strong> atributo entonces se pue<strong>de</strong> utilizar<br />

búsqueda binaria [Kruse84].<br />

14 Se enten<strong>de</strong>rá como archivo al medio <strong>de</strong> almacenamiento físico en disco ya sea por<br />

medio <strong>de</strong> sistemas <strong>de</strong> archivos o como <strong>de</strong>vice <strong>de</strong> datos (raw <strong>de</strong>vices) <strong>de</strong>pendiendo <strong>de</strong> las<br />

características <strong>de</strong>l motor <strong>de</strong> base <strong>de</strong> datos y <strong>de</strong>l sistema operativo que lo soporta.<br />

A1<br />

r<br />

73


⎡CS(<br />

A,<br />

r)<br />

⎤<br />

⎢ ⎥<br />

⎢ f r ⎥<br />

El costo estimado será : = ⎡ ( ) ⎤+ −1<br />

Basado en la suposición <strong>de</strong> que los bloques <strong>de</strong> la r<strong>el</strong>ación se almacenan <strong>de</strong><br />

manera contigua en <strong>el</strong> disco, don<strong>de</strong> ⎡log 2 ( r ) ⎤<br />

C<br />

A2<br />

log 2<br />

b<br />

r<br />

74<br />

b es <strong>el</strong> costo <strong>de</strong> localizar la primera<br />

⎡CS(<br />

A,<br />

r)<br />

⎤<br />

tupla por medio <strong>de</strong> búsqueda binaria, y ⎢ ⎥ −1<br />

es <strong>el</strong> número <strong>de</strong> bloques que<br />

⎢ f r ⎥<br />

cumplen la condición <strong>de</strong> igualdad sobre <strong>el</strong> atributo A menos <strong>el</strong> bloque que se ha<br />

rescatado con la búsqueda binaria.<br />

5.3.1.2. Exploraciones con índices.<br />

Se <strong>de</strong>nomina “camino <strong>de</strong> acceso” (access path) a cada una <strong>de</strong> las formas<br />

<strong>de</strong> acce<strong>de</strong>r a los registros <strong>de</strong> una tabla por medio <strong>de</strong> la utilización <strong>de</strong> índices. Se<br />

entien<strong>de</strong> como índice primario al índice que permite recorrer los registros <strong>de</strong> una<br />

tabla en un or<strong>de</strong>n que coinci<strong>de</strong> con <strong>el</strong> or<strong>de</strong>n físico <strong>de</strong> la tabla, un índice que no es<br />

primario se <strong>de</strong>nomina índice secundario. En sybase, un índice en cluster siempre<br />

recibe <strong>el</strong> número 1 <strong>de</strong>ntro <strong>de</strong>l conjunto <strong>de</strong> índices que pertenecen a una tabla en<br />

estrecha r<strong>el</strong>ación con la <strong>de</strong>finición <strong>de</strong> índice primario.<br />

Los algoritmos <strong>de</strong> búsqueda que utilizan un índice reciben <strong>el</strong> nombre <strong>de</strong><br />

“exploraciones <strong>de</strong> índice” o “in<strong>de</strong>x scan”. Aunque los índices aseguran la mayor<br />

v<strong>el</strong>ocidad <strong>de</strong> acceso a los datos, su utilización implica <strong>el</strong> acceso a los bloques<br />

propios <strong>de</strong>l índice, lo que se pue<strong>de</strong> consi<strong>de</strong>rar como un gasto adicional y <strong>el</strong> cual<br />

<strong>de</strong>be ser tomado en cuenta en la <strong>el</strong>aboración <strong>de</strong> algoritmos <strong>de</strong> acceso a los datos.<br />

Los siguientes algoritmos son los algoritmos <strong>de</strong> acceso a datos por medio<br />

<strong>de</strong> índices, ya sea primarios o secundarios.


A3. (índice primario, igualdad en la clave): Dado que <strong>el</strong> índice está construido<br />

sobre <strong>el</strong> (los) atributos claves, la búsqueda pue<strong>de</strong> utilizar este índice <strong>para</strong> rescatar<br />

los datos. Por lo tanto <strong>para</strong> recuperar <strong>el</strong> único registro que cumple con la condición<br />

se necesita leer sólo un bloque.<br />

El costo estimado será:<br />

C<br />

A3<br />

= AAi<br />

+ 1<br />

A4. (índice primario, igualdad basada en un atributo no clave): El costo está<br />

<strong>de</strong>terminado por la cantidad <strong>de</strong> bloques que contienen registros que cumplen con<br />

la condición <strong>de</strong> igualdad más la altura <strong>de</strong>l índice.<br />

Ejemplo: supóngase que<br />

n viaje = 36000,<br />

b viaje = 2391,<br />

t viaje = 136,<br />

f viaje = 15,<br />

⎡CS(<br />

A,<br />

r)<br />

⎤<br />

El costo estimado será: C A4<br />

= ⎢ ⎥ + AAi<br />

⎢ fr<br />

⎥<br />

que existe un índice B+ primario <strong>para</strong> las columnas PATENTE+CORRELATIVO.<br />

Se <strong>de</strong>sea s<strong>el</strong>eccionar todos las tuplas <strong>de</strong> la tabla viajes que tengan como patente<br />

= ‘HL-8483’.<br />

Como V(PATENTE,VIAJES) =30, se estima que 36000/30=1200 tuplas <strong>de</strong> la<br />

r<strong>el</strong>ación viajes sean <strong>de</strong>l móvil con patente ‘HL-8483’. Se pue<strong>de</strong> utilizar <strong>el</strong> índice<br />

primario <strong>para</strong> leer los 1200/15=80 bloques que cumplen con la condición.<br />

75


Ahora bien, supongamos que <strong>el</strong> índice tiene un tamaño <strong>de</strong>l puntero a disco<br />

<strong>de</strong> 8 bytes, sabiendo que <strong>el</strong> tamaño <strong>de</strong> la clave <strong>de</strong>l índice es <strong>de</strong> 12 bytes es lógico<br />

pensar que <strong>para</strong> un bloque <strong>de</strong> 2 Kb. El número <strong>de</strong> claves por bloque <strong>de</strong> índice es<br />

aproximadamente 100. Entonces, una búsqueda por <strong>el</strong> índice necesitará a lo sumo<br />

⎡log50 ( 36000)<br />

⎤<br />

= 3 accesos a bloques <strong>de</strong> disco, por lo tanto <strong>el</strong> número total <strong>de</strong><br />

bloques a disco a leer es <strong>de</strong> 83 (Una explicación acerca <strong>de</strong> los cálculos realizados<br />

<strong>para</strong> la estimación <strong>de</strong> accesos a bloques se pue<strong>de</strong> encontrar en <strong>el</strong> apéndice B).<br />

A5. (Índice secundario, igualdad): Si <strong>el</strong> campo in<strong>de</strong>xado no es clave se asume<br />

que se rescatará CS(A,r) registros, como <strong>el</strong> índice es secundario se estudia <strong>el</strong> peor<br />

caso, <strong>el</strong> cual propone que cada uno <strong>de</strong> los registros se encuentra en un bloque<br />

diferente, por lo tanto <strong>el</strong> costo <strong>de</strong> este caso es :<br />

C A 5 = AAi<br />

+ CS(<br />

A,<br />

r)<br />

o<br />

C A5<br />

= AAi<br />

+ 1 si <strong>el</strong> atributo es clave.<br />

A6. (Índice primario, <strong>de</strong>sigualdad): Si lo que se <strong>de</strong>sea es una s<strong>el</strong>ección <strong>de</strong>l tipo<br />

σ (r)<br />

con v disponible en <strong>el</strong> momento <strong>de</strong> la estimación <strong>de</strong>l costo y asumiendo<br />

A≤v<br />

que los datos <strong>de</strong>l atributo A se distribuyen uniformemente entonces, <strong>el</strong> número <strong>de</strong><br />

registros que cumplen con la <strong>de</strong>sigualdad es :<br />

n σ = 0 si v < min(A,r)<br />

n = n r si v > max(A,r)<br />

σ<br />

n σ =<br />

v − min( A,<br />

r)<br />

nr ⋅ en otro caso.<br />

max( A,<br />

r)<br />

− min( A,<br />

r)<br />

76


En cuanto al costo:<br />

Dado que <strong>el</strong> índice es primario se sabe que la tabla está or<strong>de</strong>nada por <strong>el</strong><br />

valor <strong>de</strong> la clave, por lo tanto, si <strong>el</strong> operador es > ó >= se realiza una búsqueda por<br />

<strong>el</strong> índice primario <strong>para</strong> encontrar a v en A y luego se realiza un recorrido lineal<br />

partiendo <strong>de</strong>s<strong>de</strong> esta tupla y hasta <strong>el</strong> fin <strong>de</strong> la tabla, lo que <strong>de</strong>volverá todas las<br />

tuplas que cumplen con la condición A >= v. Para una <strong>de</strong>sigualdad <strong>de</strong>l tipo < ó


No siempre es conveniente utilizar los índices <strong>para</strong> recuperar rangos <strong>de</strong><br />

valores, considérese <strong>el</strong> siguiente ejemplo:<br />

Supóngase que la la información estadística es la misma que se<br />

proporcionó anteriormente, que existe un índice B+ secundario <strong>para</strong> la columna<br />

TARIFA <strong>de</strong> la tabla viajes y que se <strong>de</strong>sea s<strong>el</strong>eccionar todas las tuplas <strong>de</strong> la tabla<br />

viajes que tengan una tarifa menor a 5000.<br />

Como <strong>el</strong> tamaño <strong>de</strong> la clave <strong>de</strong>l índice es <strong>de</strong> 4 bytes, es lógico pensar que<br />

en una página <strong>de</strong> índice caben 170 claves. Por lo tanto <strong>el</strong> índice necesita<br />

⎡log85 ( 36000)<br />

⎤<br />

= 3 accesos a bloques <strong>de</strong> disco <strong>para</strong> recuperar la primera hoja <strong>de</strong>l<br />

índice que se va a ocupar. Suponiendo que existen 600 valores distintos <strong>de</strong> tarifas,<br />

entonces existen entre 600/170 ≅ 4 a 8 nodos hojas en <strong>el</strong> árbol, por lo que, en <strong>el</strong><br />

peor <strong>de</strong> los casos se <strong>de</strong>ben leer 8/2 = 4 bloques <strong>de</strong> índices más 36000/2 = 18000<br />

accesos a bloques <strong>de</strong> datos. Por lo tanto, <strong>el</strong> costo <strong>de</strong> este camino <strong>de</strong> acceso es <strong>de</strong><br />

18000+4+3 = 18007.<br />

Por <strong>el</strong> contrario un full scan sobre la tabla empleará solamente b viaje = 2391<br />

bloques en vez <strong>de</strong> los 18007 calculados <strong>para</strong> <strong>el</strong> camino <strong>de</strong> acceso por índice<br />

secundario, por lo tanto, <strong>de</strong> presentarse este ejemplo, <strong>el</strong> optimizador <strong>de</strong> <strong>consultas</strong><br />

optará por un full scan.<br />

5.3.2. Conjunción, Disyunción y Negación.<br />

Conjunción.<br />

Una s<strong>el</strong>ección conjuntiva es expresión una <strong>de</strong> la forma<br />

σ θ 1∧<br />

θ 2...<br />

∧θm<br />

78<br />

( r)<br />

Suponiendo que cada una <strong>de</strong> las condiciones θi es in<strong>de</strong>pendiente <strong>de</strong> las otras se<br />

.


pue<strong>de</strong> estimar <strong>el</strong> tamaño <strong>de</strong> cada s<strong>el</strong>ección = σ (r ) . La probabilidad <strong>de</strong> que<br />

ti θi<br />

una tupla satisfaga la condición <strong>de</strong> s<strong>el</strong>ección es<br />

t<br />

n<br />

i<br />

r<br />

79<br />

(llamada s<strong>el</strong>ectividad <strong>de</strong> la<br />

s<strong>el</strong>ección) y la probabilidad <strong>de</strong> que una tupla satisfaga la conjunción <strong>de</strong><br />

s<strong>el</strong>ecciones es <strong>el</strong> producto <strong>de</strong> todas estas probabilida<strong>de</strong>s.<br />

Como<br />

Por lo tanto se estima <strong>el</strong> tamaño <strong>de</strong> la s<strong>el</strong>ección completa como:<br />

Disyunción.<br />

n<br />

r<br />

t<br />

⋅<br />

1<br />

⋅ t<br />

2<br />

⋅ t<br />

n<br />

3<br />

m<br />

r<br />

⋅ ... ⋅ t<br />

Una s<strong>el</strong>ección disyuntiva es una expresión <strong>de</strong> la forma<br />

ti <strong>de</strong>nota la probabilidad <strong>de</strong> que una tupla cumpla i<br />

n<br />

r<br />

m<br />

σ θ 1∨<br />

θ 2...<br />

∨θm<br />

( r)<br />

θ entonces, la<br />

probabilidad <strong>de</strong> que una tupla cumpla la disyunción es 1 menos la probabilidad <strong>de</strong><br />

que no cumpla ninguna <strong>de</strong> las condiciones.<br />

1 −<br />

( 1<br />

t1<br />

t 2 t m<br />

− ) ⋅ ( 1 − ) ⋅ ... ⋅ ( 1 − )<br />

n n n<br />

r<br />

por lo tanto, al multiplicar este valor por n r se obtiene <strong>el</strong> número <strong>de</strong> tuplas<br />

que satisfacen la r<strong>el</strong>ación.<br />

Negación.<br />

r<br />

r<br />

.


Como <strong>el</strong> resultado <strong>de</strong> una negación son simplemente las tuplas <strong>de</strong> r que no<br />

están en σ (r)<br />

, entonces <strong>el</strong> número <strong>de</strong> tuplas que cumplen con la condición <strong>de</strong><br />

θ<br />

negación es:<br />

tamaño θ<br />

( r)<br />

− tamaño(<br />

σ ( r))<br />

Algoritmos <strong>para</strong> la conjunción y disyunción.<br />

A8.(s<strong>el</strong>ección conjuntiva utilizando un índice simple): primero hay que<br />

<strong>de</strong>terminar si hay disponible un camino <strong>de</strong> acceso a una <strong>de</strong> las condiciones<br />

simples, <strong>de</strong> ser así, se pue<strong>de</strong> utilizar cualquier algoritmo <strong>de</strong>l A1 al A7. Luego, en<br />

memoria intermedia se verifica que los registros cumplan <strong>el</strong> resto <strong>de</strong> las<br />

condiciones. Se utiliza la s<strong>el</strong>ectividad <strong>de</strong> las condiciones <strong>para</strong> <strong>de</strong>terminar en que<br />

or<strong>de</strong>n efectuar las s<strong>el</strong>ecciones. La condición más s<strong>el</strong>ectiva (la que tiene la<br />

s<strong>el</strong>ectividad más pequeña) recupera un mayor número <strong>de</strong> registros, por lo tanto<br />

esta condición se <strong>de</strong>be comprobar en primer lugar.<br />

A9.(s<strong>el</strong>ección conjuntiva, índice compuesto): si la s<strong>el</strong>ección especifica una<br />

condición <strong>de</strong> igualdad en dos o más atributos y existe un índice compuesto en<br />

estos campos, se podría buscar en <strong>el</strong> índice directamente. El tipo <strong>de</strong> índice<br />

<strong>de</strong>termina cual <strong>de</strong> los algoritmos A3, A4 o A5 se utilizará.<br />

A10.(s<strong>el</strong>ección conjuntiva, intersección <strong>de</strong> i<strong>de</strong>ntificadores): este algoritmo<br />

utiliza índices con punteros a registros en los campos involucrados <strong>para</strong> cada<br />

condición individual. De este modo se examina cada índice en busca <strong>de</strong> punteros<br />

cuyas tuplas cumplan alguna condición individual. La intersección <strong>de</strong> todos los<br />

punteros recuperados forma <strong>el</strong> conjunto <strong>de</strong> punteros a tuplas que satisfacen la<br />

condición conjuntiva.<br />

80


A11. (s<strong>el</strong>ección disyuntiva mediante la unión <strong>de</strong> i<strong>de</strong>ntificadores): al igual que<br />

en <strong>el</strong> caso anterior se utilizan los caminos <strong>de</strong> acceso en cada una <strong>de</strong> las<br />

condiciones, la unión <strong>de</strong> los punteros forma <strong>el</strong> conjunto <strong>de</strong> punteros a tuplas que<br />

satisfacen la condición disyuntiva, sin embargo se <strong>de</strong>berá efectuar una búsqueda<br />

lineal si sólo una <strong>de</strong> las condiciones (o más) no tiene caminos <strong>de</strong> acceso.<br />

Ejemplo:<br />

Dada la consulta :<br />

SELECT * FROM VIAJES WHERE PATENTE = ‘HL-8483’ AND TARIFA = 2000<br />

Suponiendo que la información estadística es la misma <strong>de</strong> los ejemplos<br />

anteriores, si se utiliza <strong>el</strong> índice que contiene <strong>el</strong> atributo PATENTE se necesitan 83<br />

accesos a disco como se observo anteriormente.<br />

Si se utiliza <strong>el</strong> índice en TARIFA, como hay 600 valores diferentes en <strong>el</strong><br />

atributo tarifa, significa que CS(TARIFA,VIAJES) = 36000/600 = 60; por lo que en <strong>el</strong><br />

peor <strong>de</strong> los casos hay que leer 60 bloques <strong>de</strong> disco <strong>para</strong> recuperar cada una <strong>de</strong><br />

las tuplas. Se sabe a<strong>de</strong>más que la altura <strong>de</strong>l índice en <strong>el</strong> atributo tarifa es <strong>de</strong> 3, por<br />

lo tanto se necesitan sólo 60+3=63 accesos a disco a diferencia <strong>de</strong> las 83 que se<br />

necesitan por medio <strong>de</strong>l uso <strong>de</strong>l índice primario.<br />

Otra técnica que se pue<strong>de</strong> utilizar es la <strong>de</strong> intersección <strong>de</strong> i<strong>de</strong>ntificadores.<br />

Para este efecto se sabe que ambos índices tienen altura = 3. <strong>para</strong> <strong>el</strong> índice<br />

primario, <strong>el</strong> número <strong>de</strong> punteros a recuperar es 1200 los cuales caben en<br />

1200/100 = 12 bloques <strong>de</strong> índice, <strong>para</strong> <strong>el</strong> índice secundario <strong>el</strong> número <strong>de</strong> punteros<br />

a rescatar es <strong>de</strong> 60 los cuales caben en una sola página. Por lo que hasta <strong>el</strong><br />

momento se necesitan 6 + 12 + 1 = 19 bloques. Para los bloques <strong>de</strong> datos se<br />

81


necesita estimar la cantidad <strong>de</strong> tuplas que cumplen con la conjunción, como<br />

CS(PATENTE,VIAJES)=1200 y CS(TARIFA,VIAJES)=60 entonces se sabe que<br />

(1200*60)/36000 = 2 registros cumplen con la condición conjuntiva, los que en <strong>el</strong><br />

peor <strong>de</strong> los casos se rescatan con 2 accesos a bloques <strong>de</strong> disco, por lo tanto este<br />

algoritmo ocupa un total <strong>de</strong> 21 accesos a disco a diferencia <strong>de</strong> los 63 que ocupa <strong>el</strong><br />

camino <strong>de</strong> acceso <strong>de</strong>l índice secundario. Esta estimación se fundamenta en la<br />

suposición <strong>de</strong> que la distribución <strong>de</strong> los datos en PATENTES y en TARIFAS es<br />

in<strong>de</strong>pendiente y <strong>de</strong> que ambos atributos están distribuidos uniformemente en la<br />

r<strong>el</strong>ación.<br />

5.3.3. JOIN.<br />

Estimación <strong>de</strong>l tamaño.<br />

Sean r(R) y s(S) dos r<strong>el</strong>aciones:<br />

Si R I S=∅ entonces r s es lo mismo que r x s, y por lo tanto se pue<strong>de</strong><br />

utilizar la estimación <strong>de</strong>l producto cartesiano.<br />

Si R I S es una clave <strong>de</strong> R entonces <strong>el</strong> número <strong>de</strong> tuplas en r s no es<br />

mayor que <strong>el</strong> número <strong>de</strong> tuplas en S. Si R I S es una clave externa <strong>de</strong> R entonces <strong>el</strong><br />

número <strong>de</strong> tuplas <strong>de</strong> r s es exactamente <strong>el</strong> número <strong>de</strong> tuplas <strong>de</strong> S.<br />

Si R I S no es clave <strong>de</strong> R ni <strong>de</strong> S entonces se supone que cada valor<br />

aparece con la misma probabilidad , por lo tanto, sea t una tupla <strong>de</strong> r y sea<br />

R I S={A}, entonces se estima que la tupla t produce :<br />

ns<br />

CS(<br />

A,<br />

s)<br />

=<br />

V ( A,<br />

s)<br />

82


tuplas en s, por lo tanto se estima <strong>el</strong> tamaño <strong>de</strong> r s =<br />

al cambiar los pap<strong>el</strong>es <strong>de</strong> r y s se tiene<br />

nr ⋅ ns<br />

V ( A,<br />

r)<br />

nr ⋅ ns<br />

V ( A,<br />

s)<br />

Estos valores serán distintos si y sólo si V(A,r) ≠ V(A,s), si este es <strong>el</strong> caso, la<br />

más baja estimación <strong>de</strong> ambas será la más conveniente.<br />

Algoritmos.<br />

5.3.3.1. Join en bucles anidados.<br />

Si z = r s, r recibirá <strong>el</strong> nombre <strong>de</strong> r<strong>el</strong>ación externa y s se llamará r<strong>el</strong>ación<br />

interna, <strong>el</strong> algoritmo <strong>de</strong> bucles anidados se pue<strong>de</strong> presentar como sigue.<br />

resultado<br />

<strong>para</strong> cada tupla tr en r<br />

<strong>para</strong> cada tupla ts en s<br />

si (tr,ts) satisface la condición θ entonces añadir tr • ts al<br />

Algoritmo 5-1 - Join en bucles anidados.<br />

Don<strong>de</strong> tr • ts será la concatenación <strong>de</strong> las tuplas tr y ts .<br />

Como <strong>para</strong> cada registro <strong>de</strong> r se tiene que realizar una exploración<br />

completa <strong>de</strong> s, y suponiendo <strong>el</strong> peor caso, en <strong>el</strong> cual la memoria intermedia sólo<br />

pue<strong>de</strong> concatenar un bloque <strong>de</strong> cada r<strong>el</strong>ación, entonces <strong>el</strong> número <strong>de</strong> bloques a<br />

acce<strong>de</strong>r es <strong>de</strong> br + nr<br />

⋅ bs<br />

. Por otro lado, en <strong>el</strong> mejor <strong>de</strong> los casos si se pue<strong>de</strong>n<br />

(a)<br />

(b)<br />

83


contener ambas r<strong>el</strong>aciones en la memoria intermedia entonces sólo se<br />

necesitarían b r + bs<br />

accesos a bloques.<br />

Ahora bien, si la más pequeña <strong>de</strong> ambas r<strong>el</strong>aciones cabe completamente<br />

en la memoria, es conveniente utilizar esta r<strong>el</strong>ación como la r<strong>el</strong>ación interna,<br />

utilizando así sólo b r + bs<br />

accesos a bloques.<br />

5.3.3.2. Join en bucles anidados por bloques.<br />

Una variante <strong>de</strong>l algoritmo anterior pue<strong>de</strong> lograr un ahorro en <strong>el</strong> acceso a<br />

bloques si se procesan las r<strong>el</strong>aciones por bloques en vez <strong>de</strong> por tuplas.<br />

<strong>para</strong> cada bloque Br <strong>de</strong> r<br />

<strong>para</strong> cada bloque Bs <strong>de</strong> s<br />

<strong>para</strong> cada tupla tr en Br<br />

<strong>para</strong> cada tupla ts en Bs<br />

si (tr,ts) satisface la condición θ entonces añadir tr • ts<br />

al resultado<br />

Algoritmo 5-2 - Join en bucles anidados por bloques.<br />

La diferencia principal en costos <strong>de</strong> este algoritmo con <strong>el</strong> anterior es que en<br />

<strong>el</strong> peor <strong>de</strong> los casos cada bloque <strong>de</strong> la r<strong>el</strong>ación interna s se lee una vez por cada<br />

bloque <strong>de</strong> r y no por cada tupla <strong>de</strong> la r<strong>el</strong>ación externa, <strong>de</strong> este modo <strong>el</strong> número <strong>de</strong><br />

bloques a acce<strong>de</strong>r es <strong>de</strong> br + br<br />

⋅ bs<br />

don<strong>de</strong> a<strong>de</strong>más resulta más conveniente utilizar<br />

la r<strong>el</strong>ación más pequeña como la r<strong>el</strong>ación externa.<br />

84


5.3.3.3. Join en bucles anidados por índices.<br />

Este algoritmo simplemente sustituye las búsquedas en tablas por<br />

búsquedas en índices, esto pue<strong>de</strong> ocurrir siempre y cuando exista un índice en <strong>el</strong><br />

atributo <strong>de</strong> join <strong>de</strong> la r<strong>el</strong>ación interna. Este método se utiliza cuando existen<br />

índices así como cuando se crean índices temporales con <strong>el</strong> único propósito <strong>de</strong><br />

evaluar la reunión.<br />

El costo <strong>de</strong> este algoritmo se pue<strong>de</strong> calcular como sigue: <strong>para</strong> cada tupla <strong>de</strong><br />

la r<strong>el</strong>ación externa r se realiza una búsqueda en <strong>el</strong> índice <strong>de</strong> s <strong>para</strong> recuperar las<br />

tuplas apropiadas, sea c = costo <strong>de</strong> la búsqueda en <strong>el</strong> índice, <strong>el</strong> cual se pue<strong>de</strong><br />

calcular con cualquiera <strong>de</strong> los algoritmos A3, A4 o A5. Entonces <strong>el</strong> costo <strong>de</strong>l join<br />

es + n ⋅ c ; si hay índices disponibles <strong>para</strong> <strong>el</strong> atributo <strong>de</strong> join en ambas<br />

br r<br />

r<strong>el</strong>aciones, es conveniente utilizar la r<strong>el</strong>ación con menos tuplas.<br />

5.3.3.4. Join por mezcla.<br />

El algoritmo <strong>de</strong> Join por mezcla se pu<strong>de</strong> utilizar <strong>para</strong> calcular un Join natural<br />

o un equi-join. Para tales efectos ambas r<strong>el</strong>aciones <strong>de</strong>ben estar or<strong>de</strong>nadas por los<br />

atributos en común.<br />

Este algoritmo asocia un puntero a cada r<strong>el</strong>ación, al principio estos punteros<br />

apuntan al inicio <strong>de</strong> cada una <strong>de</strong> la r<strong>el</strong>aciones. Según avanza <strong>el</strong> algoritmo, <strong>el</strong><br />

puntero se mueve a través <strong>de</strong> la r<strong>el</strong>ación. De este modo se leen en memoria un<br />

grupo <strong>de</strong> tuplas <strong>de</strong> una r<strong>el</strong>ación con <strong>el</strong> mismo valor en los atributos <strong>de</strong> la reunión.<br />

85


Pr = dirección <strong>de</strong> la primera tupla <strong>de</strong> r;<br />

ps = dirección <strong>de</strong> la primera tupla <strong>de</strong> s;<br />

mientras (ps nulo y pr nulo)<br />

inicio<br />

ts = tupla a la que apunta ps;<br />

S = {ts};<br />

ps = puntero a la siguiente tupla <strong>de</strong> s;<br />

hecho = falso;<br />

mientras (not hecho y ps nulo)<br />

inicio<br />

ts' = tupla a la que apunta ps;<br />

si (ts'[AtribsReunión] = ts[AtribsReunión])<br />

S = S union {ts'};<br />

ps = puntero a la siguiente tupla <strong>de</strong> s;<br />

sino<br />

hecho = verda<strong>de</strong>ro;<br />

fin mientras;<br />

tr = tupla a la que apunta pr;<br />

mientras (pr nulo y tr[AtribsReunión] < ts[AtribsReunión])<br />

inicio<br />

pr = puntero a la siguiente tupla <strong>de</strong> r;<br />

tr = tupla a la que apunta pr;<br />

fin mientras;<br />

mientras (pr nulo y tr[AtribsReunión] = ts[AtribsReunión])<br />

inicio<br />

<strong>para</strong> cada ts en S<br />

añadir ts x tr al resultado<br />

pr = puntero a la siguiente tupla <strong>de</strong> r;<br />

tr = tupla a la que apunta pr;<br />

fin mientras<br />

fin mientras<br />

Algoritmo 5-3 - Join por mezcla.<br />

86


Dado que las r<strong>el</strong>aciones están or<strong>de</strong>nadas, las tuplas con <strong>el</strong> mismo valor en<br />

los atributos <strong>de</strong> la reunión aparecerán consecutivamente. De este modo solamente<br />

es necesario leer cada tupla en <strong>el</strong> or<strong>de</strong>n una sola vez. Puesto que sólo se hace un<br />

ciclo en ambas tablas, este método resulta eficiente; <strong>el</strong> número <strong>de</strong> accesos a<br />

bloques <strong>de</strong> disco es igual a la suma <strong>de</strong> los bloques <strong>de</strong> las dos tablas b r + bs<br />

. Si<br />

una <strong>de</strong> las r<strong>el</strong>aciones no está or<strong>de</strong>nada según los atributos comunes <strong>de</strong>l join, se<br />

pue<strong>de</strong> or<strong>de</strong>nar primero <strong>para</strong> luego utilizar <strong>el</strong> algoritmo <strong>de</strong> join por mezcla. En este<br />

caso hay que consi<strong>de</strong>rar también <strong>el</strong> costo <strong>de</strong> or<strong>de</strong>nar la o las r<strong>el</strong>aciones y sumarlo<br />

al costo <strong>de</strong> este algoritmo. Como se menciono anteriormente este algoritmo<br />

necesita que <strong>el</strong> conjunto S <strong>de</strong> tuplas quepa completamente en la memoria<br />

principal, este requisito se pue<strong>de</strong> alcanzar normalmente, incluso si la r<strong>el</strong>ación s es<br />

gran<strong>de</strong>. De no po<strong>de</strong>r cumplirse este requisito se <strong>de</strong>berá efectuar un join en bucle<br />

anidado por bloques entre {S} y r con los mismos valores en los atributos <strong>de</strong>l join,<br />

con lo que <strong>el</strong> costo <strong>de</strong>l join aumenta.<br />

Una variación <strong>de</strong> este algoritmo se pue<strong>de</strong> realizar aún en tuplas<br />

<strong>de</strong>sor<strong>de</strong>nadas si existen índices secundarios en los atributos <strong>de</strong> join <strong>de</strong> cada una<br />

<strong>de</strong> las r<strong>el</strong>aciones, sin embargo, dada la naturaleza <strong>de</strong> este tipo <strong>de</strong> caminos <strong>de</strong><br />

acceso existe una alta probabilidad <strong>de</strong> que se necesite un acceso a bloque <strong>de</strong><br />

disco por cada tupla, lo que lo hace sustancialmente más costoso. Para evitar este<br />

costo se pue<strong>de</strong> utilizar un algoritmo <strong>de</strong> join por mezcla híbrido, que combina<br />

índices con un join por mezcla. Si sólo una <strong>de</strong> las r<strong>el</strong>aciones está <strong>de</strong>sor<strong>de</strong>nada<br />

pero existe un índice secundario en <strong>el</strong> atributo <strong>de</strong> join, <strong>el</strong> algoritmo <strong>de</strong> join por<br />

mezcla híbrido combina la r<strong>el</strong>ación or<strong>de</strong>nada con las entradas hojas <strong>de</strong>l índice<br />

secundario. El resultado <strong>de</strong> esta operación se <strong>de</strong>be or<strong>de</strong>nar según las direcciones<br />

<strong>de</strong>l índice secundario permitiendo así una recuperación eficiente <strong>de</strong> las tuplas,<br />

según <strong>el</strong> or<strong>de</strong>n físico <strong>de</strong> almacenamiento.<br />

87


5.3.3.5. Join por asociación.<br />

Al igual que <strong>el</strong> algoritmo <strong>de</strong> join por mezcla, <strong>el</strong> algoritmo <strong>de</strong> join por<br />

asociación se pue<strong>de</strong> utilizar <strong>para</strong> un Join natural o un equi-join. Este algoritmo<br />

utiliza una función <strong>de</strong> asociación h <strong>para</strong> dividir las tuplas <strong>de</strong> ambas r<strong>el</strong>aciones. La<br />

i<strong>de</strong>a fundamental es dividir las tuplas <strong>de</strong> cada r<strong>el</strong>ación en conjuntos con <strong>el</strong> mismo<br />

valor <strong>de</strong> la función <strong>de</strong> asociación en los atributos <strong>de</strong> join.<br />

Se supone que:<br />

• h es una función <strong>de</strong> asociación que asigna a los atributos <strong>de</strong> join los valores<br />

•<br />

{0,1,...max}<br />

• r , H ,...<br />

0 r H 1 rmax<br />

H <strong>de</strong>notan las particiones <strong>de</strong> las tuplas <strong>de</strong> r, inicialmente todas<br />

vacías. Cada tupla r t se pone en la partición H r don<strong>de</strong><br />

i<br />

( t [ Atributos _ <strong>de</strong> Join]<br />

)<br />

i = h r _<br />

• H s , H s ,... H s <strong>de</strong>notan las particiones <strong>de</strong> las tuplas <strong>de</strong> s, inicialmente todas<br />

0 1<br />

max<br />

vacías. Cada tupla ts se pone en la partición H s don<strong>de</strong><br />

i<br />

( t [ Atributos _ <strong>de</strong> Join]<br />

)<br />

i = h s _<br />

La i<strong>de</strong>a <strong>de</strong>trás <strong>de</strong>l algoritmo es la siguiente, supóngase que una tupla <strong>de</strong> r y<br />

una tupla <strong>de</strong> s satisfacen la condición <strong>de</strong> join y por lo tanto tienen los mismos<br />

valores en los atributos <strong>de</strong> join. Si estos valores se asocian con algún valor i,<br />

entonces la tupla <strong>de</strong> r tiene que estar en H r y la tupla <strong>de</strong> s tiene que estar en H i<br />

s , i<br />

<strong>de</strong> este modo sólo será necesario com<strong>para</strong>r las tuplas <strong>de</strong> r en H r con las tuplas<br />

i<br />

<strong>de</strong> s en H s y no con las tuplas <strong>de</strong> s <strong>de</strong> otra partición.<br />

i<br />

88


tuplas<br />

t r<br />

El algoritmo es <strong>el</strong> siguiente.<br />

<strong>para</strong> cada tupla t s en s<br />

fin <strong>para</strong>;<br />

( t [ Atributos _ <strong>de</strong> Join]<br />

)<br />

i = h s _ ;<br />

= H s U{<br />

ts}<br />

;<br />

H si<br />

i<br />

<strong>para</strong> cada tupla tr en r<br />

( t [ Atributos _ <strong>de</strong> Join]<br />

)<br />

i = h r _ ;<br />

= H r U{<br />

tr}<br />

;<br />

H ri<br />

i<br />

fin <strong>para</strong>;<br />

<strong>para</strong> i = 1 hasta max<br />

[ Atributos <strong>de</strong> _ Join]<br />

leer H s y construir un índice asociativo en memoria sobre él;<br />

i<br />

<strong>para</strong> cada tupla tr en H ri<br />

_ ;<br />

fin <strong>para</strong>;<br />

fin <strong>para</strong>;<br />

fin <strong>para</strong>;<br />

explorar <strong>el</strong> índice asociativo en H s <strong>para</strong> localizar todas las<br />

i<br />

tales que [ Atributos <strong>de</strong> _ Join]<br />

<strong>para</strong> cada tupla ts que concuer<strong>de</strong> en H si<br />

añadir tr x ts al resultado;<br />

t s<br />

Algoritmo 5-4 - Join por asociación.<br />

_ =<br />

89


El índice asociativo (ver Apéndice B) en H s se construye en memoria por lo<br />

i<br />

que no se hace necesario acce<strong>de</strong>r al disco <strong>para</strong> recuperar las tuplas, la función <strong>de</strong><br />

asociación utilizada <strong>para</strong> construir este índice es distinta a la función h utilizada<br />

<strong>para</strong> construir las particiones. Después <strong>de</strong> la división <strong>de</strong> las r<strong>el</strong>aciones <strong>el</strong> resto <strong>de</strong>l<br />

código realiza un join en bucle anidado por índices en cada una <strong>de</strong> las particiones.<br />

Para lograr esto primero se construye un índice asociativo en cada H s y luego se<br />

i<br />

prueba (se busca en H s ) con las tuplas <strong>de</strong> H i<br />

r . i<br />

Se tiene que <strong>el</strong>egir <strong>el</strong> valor <strong>de</strong> max lo suficientemente gran<strong>de</strong> como <strong>para</strong><br />

que, <strong>para</strong> cada i, las tuplas <strong>de</strong> la partición H s junto con <strong>el</strong> índice asociativo <strong>de</strong> la<br />

i<br />

r<strong>el</strong>ación quepan completamente en la memoria. Claramente será más conveniente<br />

utilizar la r<strong>el</strong>ación más pequeña como la r<strong>el</strong>ación s. Si <strong>el</strong> tamaño <strong>de</strong> la r<strong>el</strong>ación s es<br />

bs bloques, entonces <strong>para</strong> que cada una <strong>de</strong> las max particiones tengan un tamaño<br />

menor o igual a M, max <strong>de</strong>be ser al menos ⎡bs / M ⎤ más <strong>el</strong> espacio adicional<br />

ocupado por <strong>el</strong> índice asociativo. Una consi<strong>de</strong>ración a seguir <strong>para</strong> que las<br />

divisiones <strong>de</strong> las r<strong>el</strong>aciones se efectúe en un solo paso es que M>max+1 o<br />

equivalentemente si M>( b/M)+1 s que <strong>de</strong> manera aproximada se simplifica a<br />

M > bs<br />

. Por ejemplo, si una r<strong>el</strong>ación contiene 440 bloques <strong>de</strong> 2KB cada uno,<br />

entonces M > 440 , osea M > 20. De tal manera sólo se necesitarán 40 Kb. <strong>de</strong><br />

espacio <strong>de</strong> memoria (más <strong>el</strong> espacio requerido por <strong>el</strong> índice asociativo) <strong>para</strong> <strong>el</strong><br />

particionamiento <strong>de</strong> la r<strong>el</strong>ación.<br />

El cálculo <strong>de</strong>l costo <strong>de</strong> un join por asociación tiene la siguiente lógica: <strong>el</strong><br />

particionamiento <strong>de</strong> ambas r<strong>el</strong>aciones reclama una lectura completa <strong>de</strong> cada<br />

r<strong>el</strong>ación, como también su posterior escritura, esta operación necesita 2( b r + bs<br />

)<br />

accesos a bloques. Las fases <strong>de</strong> construcción y prueba (como se le <strong>de</strong>nomina al<br />

join en bucle anidado por índices) lee cada una <strong>de</strong> las particiones una vez<br />

90


empleando b r + bs<br />

accesos adicionales. El número <strong>de</strong> bloques ocupados por las<br />

particiones podría ser ligeramente mayor que b r + bs<br />

. Debido a que los bloques no<br />

están completamente llenos,. El acceso a estos bloques pue<strong>de</strong> añadir un gasto<br />

adicional <strong>de</strong> 2·max a lo sumo, ya que cada una <strong>de</strong> las particiones podría tener un<br />

bloque parcialmente ocupado que se tiene que leer y escribir <strong>de</strong> nuevo. Así <strong>el</strong><br />

costo estimado <strong>para</strong> un join por asociación es :<br />

3( b r + bs<br />

) + 2 ⋅ max<br />

5.3.3.6. Join por asociación híbrida.<br />

El algoritmo <strong>de</strong> join por asociación híbrida realiza otra optimización; es útil<br />

cuando <strong>el</strong> tamaño <strong>de</strong> la memoria es r<strong>el</strong>ativamente gran<strong>de</strong> paro aún así, no cabe<br />

toda la r<strong>el</strong>ación s en memoria. Dado que <strong>el</strong> algoritmo <strong>de</strong> join por asociación<br />

necesita max +1 bloques <strong>de</strong> memoria <strong>para</strong> dividir ambas r<strong>el</strong>aciones se pue<strong>de</strong><br />

utilizar <strong>el</strong> resto <strong>de</strong> la memoria (M – max – 1 bloques) <strong>para</strong> guardar en la memoria<br />

intermedia la primera partición <strong>de</strong> la r<strong>el</strong>ación s, esto es H s , así no es necesaria<br />

0<br />

leerla ni escribirla nuevamente y se pue<strong>de</strong> construir un índice asociativo en H s . 0<br />

Cuando r se divi<strong>de</strong>, las tuplas <strong>de</strong> H r tampoco se escriben en disco; en su<br />

0<br />

lugar, según se van generando, <strong>el</strong> sistema las utiliza <strong>para</strong> examinar <strong>el</strong> índice<br />

asociativo en H s y así generar las tuplas <strong>de</strong> salida <strong>de</strong>l join. Después <strong>de</strong> utilizarlas,<br />

0<br />

estas tuplas se <strong>de</strong>scartan, así que la partición H r no ocupa espacio en memoria.<br />

0<br />

De este modo se ahorra un acceso <strong>de</strong> lectura y uno <strong>de</strong> escritura <strong>para</strong> cada bloque<br />

<strong>de</strong> H r y H 0 s . Las tuplas <strong>de</strong> otras particiones se escriben <strong>de</strong> la manera usual <strong>para</strong><br />

0<br />

reunirlas más tar<strong>de</strong>.<br />

91


5.3.3.7. Join Complejos.<br />

Los join en bucle anidado y en bucle anidado por bloques son útiles<br />

siempre, sin embargo, las otras técnicas <strong>de</strong> join son más eficientes que estas,<br />

pero sólo se pue<strong>de</strong>n utilizar en condiciones particulares tales como join natural o<br />

equi-join. Se pue<strong>de</strong>n implementar join con condiciones más complejas tales como<br />

conjunción o disyunción, aplicando las técnicas <strong>de</strong>sarrolladas en la sección 5.3.2<br />

<strong>para</strong> <strong>el</strong> manejo <strong>de</strong> s<strong>el</strong>ecciones complejas.<br />

Dado un join <strong>de</strong> las forma r θ ∧ θ ∧...<br />

∧θ<br />

s se pue<strong>de</strong>n aplicar una o más <strong>de</strong> las<br />

1 2 n<br />

técnicas <strong>de</strong> join <strong>de</strong>scritas anteriormente en cada condición individual r θ s , <strong>el</strong><br />

i<br />

resultado total consiste en las tuplas <strong>de</strong>l resultado intermedio que satisfacen <strong>el</strong><br />

resto <strong>de</strong> las condiciones. Estas condiciones se pue<strong>de</strong>n ir comprobado según se<br />

generen las tuplas <strong>de</strong> r θ s . La implementación <strong>de</strong> la disyunción es homóloga a<br />

i<br />

la conjunción.<br />

Outer Join (Join externos)<br />

Un outer join es una extensión <strong>de</strong>l operador join que se utiliza a menudo<br />

<strong>para</strong> trabajar con la información que falta. Por ejemplo, suponiendo que se <strong>de</strong>sea<br />

generar una lista con todos los choferes y los autos que manejan (si manejan<br />

alguno) entonces se <strong>de</strong>be cruzar la r<strong>el</strong>ación Chofer con la r<strong>el</strong>ación Movil. Si se<br />

efectúa un join corriente se per<strong>de</strong>rán todas aqu<strong>el</strong>las tuplas que pertenecen a los<br />

choferes, en cambio con un outer join se pue<strong>de</strong>n <strong>de</strong>splegar las tuplas resultado<br />

incluyendo a aqu<strong>el</strong>los choferes que no tengan a cargo un auto. El outer join tiene<br />

tres formas distintas: por la izquierda, por la <strong>de</strong>recha y completo. El join por la<br />

izquierda ( ]x )toma todas las tuplas <strong>de</strong> la r<strong>el</strong>ación <strong>de</strong> la izquierda que no<br />

92


coincidan con ninguna tupla <strong>de</strong> la r<strong>el</strong>ación <strong>de</strong> la <strong>de</strong>recha , las r<strong>el</strong>lena con valores<br />

nulos en los <strong>de</strong>más atributos <strong>de</strong> la r<strong>el</strong>ación <strong>de</strong> la <strong>de</strong>recha y las aña<strong>de</strong> al resultado<br />

<strong>de</strong>l join natural. Un outer join por la <strong>de</strong>recha ( x [ ) ) es análogo al procedimiento<br />

anterior y <strong>el</strong> outer join completo es aqu<strong>el</strong> que efectúa ambas operaciones.<br />

Se pue<strong>de</strong> implementar un outer join empleando una <strong>de</strong> las dos estrategias<br />

siguientes. La primera efectúa un join natural y luego aña<strong>de</strong> más tuplas al<br />

resultado hasta obtener <strong>el</strong> join externo. Sea r(R) y s(S) , <strong>para</strong> evaluar r ] x s se<br />

calcula primero r s y se guarda este resultado en la r<strong>el</strong>ación temporal q1, a<br />

continuación se calcula (q1)<br />

∏ − que produce las tuplas <strong>de</strong> r que no participan<br />

r R<br />

<strong>de</strong>l join, estas tuplas se r<strong>el</strong>lenan con valores nulos en los atributos <strong>de</strong> s y se<br />

aña<strong>de</strong>n a q1 <strong>para</strong> obtener <strong>el</strong> resultado <strong>de</strong>seado. El procedimiento es homólogo<br />

<strong>para</strong> los outer join por la <strong>de</strong>recha o completo.<br />

La segunda estrategia significa modificar <strong>el</strong> algoritmo <strong>de</strong> join. Se pu<strong>de</strong><br />

exten<strong>de</strong>r <strong>el</strong> algoritmo <strong>de</strong> join en bucles anidados <strong>para</strong> calcular <strong>el</strong> outer join por la<br />

izquierda. Las tuplas <strong>de</strong> la r<strong>el</strong>ación externa que no concuer<strong>de</strong>n con ninguna tupla<br />

<strong>de</strong> la r<strong>el</strong>ación interna se completan con valores nulos y se escriben en la salida.<br />

Para <strong>el</strong> caso <strong>de</strong> un outer join completo se pue<strong>de</strong> calcular mediante<br />

extensiones <strong>de</strong> los algoritmos <strong>de</strong> join por mezcla y join por asociación. En <strong>el</strong> caso<br />

<strong>de</strong>l algoritmo <strong>de</strong> join por mezcla, cuando se está produciendo la mezcla <strong>de</strong> ambas<br />

r<strong>el</strong>aciones, las tuplas <strong>de</strong> la r<strong>el</strong>ación que no encajan con ninguna tupla <strong>de</strong> la otra<br />

r<strong>el</strong>ación se r<strong>el</strong>lenan con valores nulos y se escriben en la salida. Puesto que las<br />

r<strong>el</strong>aciones están or<strong>de</strong>nadas, es fácil <strong>de</strong>tectar si una tupla coinci<strong>de</strong> o no con alguna<br />

tupla <strong>de</strong> la otra r<strong>el</strong>ación. El costo estimado <strong>para</strong> realizar un outer join utilizando <strong>el</strong><br />

algoritmo <strong>de</strong> join por mezcla es <strong>el</strong> mismo que si fuera un join normal, la única<br />

diferencia es <strong>el</strong> tamaño <strong>de</strong>l resultado, por lo tanto <strong>el</strong> número <strong>de</strong> bloques a escribir<br />

en <strong>el</strong> resultado pue<strong>de</strong> aumentar.<br />

93


5.3.3.8. Agregación.<br />

La agregación es otra <strong>de</strong> las características <strong>de</strong>l álgebra <strong>de</strong> r<strong>el</strong>aciones<br />

extendida. La i<strong>de</strong>a <strong>de</strong> este tipo <strong>de</strong> funciones es que tomen un conjunto <strong>de</strong> valores<br />

y que retornen un solo valor. se utilizan comúnmente <strong>para</strong> información agregada<br />

(<strong>de</strong> ahí su nombre), analizan una agrupación <strong>de</strong> registros y rescatan <strong>el</strong> valor<br />

solicitado, se aplican sobre un atributo o sobre una composición <strong>de</strong> atributos, <strong>el</strong><br />

valor retornado pue<strong>de</strong> ser min, max, count, sum, avg, que correspon<strong>de</strong>n<br />

respectivamente a <strong>el</strong> mínimo valor <strong>de</strong>l subconjunto; <strong>el</strong> máximo valor; una cuenta<br />

<strong>de</strong> valores; la suma sobre algún atributo o composición <strong>de</strong> atributos y <strong>el</strong> promedio.<br />

Para la implementación <strong>de</strong> la operación <strong>de</strong> agregación se pue<strong>de</strong> utilizar un<br />

algoritmo <strong>de</strong> or<strong>de</strong>nación o uno <strong>de</strong> asociación, <strong>para</strong> <strong>el</strong> caso <strong>de</strong> la asociación, lo que<br />

se hace es agrupar las tuplas que tengan <strong>el</strong> mismo valor en los atributos <strong>de</strong> la<br />

agregación y luego se aplica la función <strong>de</strong> agregación en cada uno <strong>de</strong> los grupos<br />

<strong>para</strong> obtener <strong>el</strong> resultado.<br />

El tamaño <strong>de</strong> la agregación sobre A es simplemente V(A,r). El costo<br />

estimado <strong>de</strong> la implementación <strong>de</strong> la agregación es <strong>el</strong> mismo <strong>de</strong> una or<strong>de</strong>nación<br />

(cualquiera sea <strong>el</strong> algoritmo).<br />

En lugar <strong>de</strong> reunir todas las tuplas en grupos y aplicar entonces las<br />

funciones <strong>de</strong> agregación, se pue<strong>de</strong>n implementar sobre la marcha según se<br />

construyen los grupos. Si las V(A,r) tuplas <strong>de</strong>l resultado caben en memoria, las<br />

implementaciones basadas en or<strong>de</strong>nación y las basadas en asociación no<br />

requieren escribir bloques adicionales a disco, según se leen las tuplas se pue<strong>de</strong>n<br />

ir insertando en una estructura or<strong>de</strong>nada <strong>de</strong> árbol o en un índice asociativo, <strong>de</strong><br />

esta manera sólo se necesitan b r transferencias <strong>de</strong> bloques.<br />

94


5.4. Evaluación <strong>de</strong> expresiones.<br />

En este apartado se consi<strong>de</strong>rará como evaluar una expresión que contiene<br />

varias operaciones, la forma intuitiva <strong>de</strong> evaluar una expresión es evaluar una<br />

operación a la vez en un or<strong>de</strong>n apropiado, <strong>el</strong> resultado <strong>de</strong> cada operación se<br />

materializa en una r<strong>el</strong>ación temporal <strong>para</strong> su inmediata utilización. El<br />

inconveniente <strong>de</strong> esta aproximación es la creación <strong>de</strong> r<strong>el</strong>aciones temporales que<br />

implican la escritura y lectura <strong>de</strong> disco. Una aproximación alternativa es evaluar<br />

operaciones <strong>de</strong> manera simultanea en un cauce, con los resultados <strong>de</strong> una<br />

operación pasados a la siguiente sin la necesidad <strong>de</strong> almacenarlos en r<strong>el</strong>aciones<br />

temporales.<br />

5.4.1. Materialización.<br />

Este enfoque <strong>de</strong> implementación toma la expresión y la representa en una<br />

estructura anexa (comúnmente un árbol <strong>de</strong> operadores). Luego se comienza por<br />

las operaciones <strong>de</strong> más bajo niv<strong>el</strong>, las entradas a estas operaciones son las<br />

r<strong>el</strong>aciones <strong>de</strong> la base <strong>de</strong> datos, estas operaciones se ejecutan utilizando los<br />

algoritmos ya estudiados y almacenando sus resultados en r<strong>el</strong>aciones temporales.<br />

Luego se utilizan estas r<strong>el</strong>aciones temporales <strong>para</strong> ejecutar las operaciones <strong>de</strong>l<br />

siguiente niv<strong>el</strong> en <strong>el</strong> árbol.<br />

Una evaluación como la <strong>de</strong>scrita se llama evaluación materializada, puesto<br />

que los resultados <strong>de</strong> cada operación intermedia se crean (materializan) con <strong>el</strong> fin<br />

<strong>de</strong> ser utilizados en la evaluación <strong>de</strong> las operaciones <strong>de</strong>l siguiente niv<strong>el</strong>.<br />

95


El costo <strong>de</strong> una evaluación materializada no es simplemente la suma <strong>de</strong> los<br />

costos <strong>de</strong> las operaciones involucradas. Dado que los costos estimados <strong>de</strong> los<br />

algoritmos presentados anteriormente no consi<strong>de</strong>ran <strong>el</strong> resultado <strong>de</strong> la operación<br />

en disco, por lo tanto, al costo <strong>de</strong> las operaciones involucradas hay que añadir <strong>el</strong><br />

costo <strong>de</strong> escribir los resultados intermedios en disco. Suponiendo que los registros<br />

<strong>de</strong>l resultado se almacenan en una memoria intermedia y que cuando esta se<br />

llena, los registros se escriben en <strong>el</strong> disco. El costo <strong>de</strong> copiar los resultados se<br />

pue<strong>de</strong> estimar en r r b n don<strong>de</strong> nr es <strong>el</strong> número aproximado <strong>de</strong> tuplas <strong>de</strong> la r<strong>el</strong>ación<br />

resultado y fr es <strong>el</strong> factor <strong>de</strong> bloqueo <strong>de</strong> la r<strong>el</strong>ación resultado.<br />

5.4.2. Encauzamiento.<br />

Se pue<strong>de</strong> mejorar la evaluación <strong>de</strong> una consulta mediante la reducción <strong>de</strong>l<br />

número <strong>de</strong> archivos temporales que se producen. Por ejemplo, considérese <strong>el</strong> join<br />

<strong>de</strong> dos r<strong>el</strong>aciones seguida <strong>de</strong> una proyección. Si se aplicara materialización en la<br />

evaluación <strong>de</strong> esta expresión implicaría la creación <strong>de</strong> una r<strong>el</strong>ación temporal <strong>para</strong><br />

guardar <strong>el</strong> resultado <strong>de</strong>l join y la posterior lectura <strong>de</strong> esta <strong>para</strong> realizar la<br />

proyección. Estas operaciones se pue<strong>de</strong>n combinar como sigue. Cuando la<br />

operación <strong>de</strong> join genera una tupla <strong>de</strong>l resultado, esta se pasa inmediatamente al<br />

operador <strong>de</strong> proyección <strong>para</strong> su procesamiento. Mediante la combinación <strong>de</strong>l join y<br />

<strong>de</strong> la proyección, se evita la creación <strong>de</strong> resultados intermedios, creando en su<br />

lugar <strong>el</strong> resultado final directamente.<br />

La implementación <strong>de</strong>l encauzamiento se pue<strong>de</strong> realizar <strong>de</strong> dos formas:<br />

1. Bajo <strong>de</strong>manda (enfoque top-down)<br />

2. Des<strong>de</strong> los procedimientos (enfoque bottom-up)<br />

96


En un encauzamiento bajo <strong>de</strong>manda <strong>el</strong> sistema reitera peticiones <strong>de</strong> tuplas<br />

<strong>de</strong>s<strong>de</strong> la operación <strong>de</strong> la cima <strong>de</strong>l encauzamiento. Cada vez que un operador<br />

recibe una petición <strong>de</strong> tuplas calcula la siguiente tupla a <strong>de</strong>volver y la envía al<br />

procesador <strong>de</strong> <strong>consultas</strong>. En un encauzamiento <strong>de</strong>s<strong>de</strong> los procedimientos, los<br />

operadores no esperan a que se produzcan peticiones <strong>para</strong> producir las tuplas, en<br />

su lugar generan las tuplas impacientemente. Cada operación <strong>de</strong>l fondo <strong>de</strong>l<br />

encauzamiento genera continuamente tuplas <strong>de</strong> salida y las coloca en las<br />

memorias intermedias <strong>de</strong> salida hasta que se llenan. Asi, cuando un operador en<br />

cualquier niv<strong>el</strong> <strong>de</strong>l encauzamiento obtiene sus tuplas <strong>de</strong> entrada <strong>de</strong> un niv<strong>el</strong><br />

inferior <strong>de</strong>l encauzamiento, produce las tuplas <strong>de</strong> salida hasta llenar su memoria<br />

intermedia <strong>de</strong> salida.<br />

El sistema necesita cambiar <strong>de</strong> una operación a otra solamente cuando se<br />

llena una memoria intermedia <strong>de</strong> salida o cuando una memoria intermedia <strong>de</strong><br />

entrada está vacía y se necesitan más tuplas <strong>de</strong> entrada <strong>para</strong> generar las tuplas<br />

<strong>de</strong> salida. Las operaciones <strong>de</strong> encauzamiento se pue<strong>de</strong>n ejecutar<br />

concurrentemente en distintos procesadores.<br />

El encauzamiento bajo <strong>de</strong>manda se utiliza comúnmente más que <strong>el</strong><br />

encauzamiento <strong>de</strong>s<strong>de</strong> los procedimientos dada su facilidad <strong>de</strong> implementación.<br />

5.4.3. Algoritmos <strong>de</strong> encauzamiento.<br />

Supóngase un join cuya entrada <strong>de</strong>l lado izquierdo esta encauzada, dado<br />

que esta entrada no está completamente disponible, implica la imposibilidad e<br />

utilizar un join por mezcla (dado que no se sabe si la esta entrada viene o no<br />

or<strong>de</strong>nada). El or<strong>de</strong>nar la r<strong>el</strong>ación significa transformar <strong>el</strong> procedimiento en<br />

materialización. Este ejemplo ilustra que la <strong>el</strong>ección respecto al algoritmo a utilizar<br />

97


<strong>para</strong> una operación y las <strong>el</strong>ecciones respecto <strong>de</strong>l encauzamiento son<br />

<strong>de</strong>pendientes una <strong>de</strong> la otra.<br />

El uso eficiente <strong>de</strong>l encauzamiento necesita la utilización <strong>de</strong> algoritmos <strong>de</strong><br />

evaluación que puedan generar tuplas <strong>de</strong> salida según se están recibiendo tuplas<br />

por la entrada <strong>de</strong> la operación. Se pue<strong>de</strong>n distinguir dos casos:<br />

1. Solamente una <strong>de</strong> las entradas está encauzada.<br />

2. Las dos entradas <strong>de</strong> un join están encauzadas.<br />

Si únicamente una <strong>de</strong> las entradas está encauzada, un join en bucle<br />

anidado in<strong>de</strong>xado es la <strong>el</strong>ección más natural, ahora bien, si se sabe <strong>de</strong> antemano<br />

que las tuplas <strong>de</strong> la entrada encauzada están or<strong>de</strong>nadas por los atributos <strong>de</strong> join y<br />

la condición <strong>de</strong> join es un equi-join también se pue<strong>de</strong> usar un join por mezcla. Se<br />

pue<strong>de</strong> utilizar un join por asociación híbrida con la entrada encauzada como la<br />

r<strong>el</strong>ación <strong>para</strong> probar (r<strong>el</strong>ación r). Sin embargo, las tuplas que no están en la<br />

primera partición se enviarán a la salida solamente <strong>de</strong>spués <strong>de</strong> que la r<strong>el</strong>ación <strong>de</strong><br />

entrada encauzada se reciba por completo. Un join por asociación híbrida es útil si<br />

la entrada no encauzada cabe completamente en memoria, o si al menos la<br />

mayoría <strong>de</strong> las entradas caben en memoria.<br />

Si ambas entradas están encauzadas, la <strong>el</strong>ección <strong>de</strong> los algoritmos <strong>de</strong> join<br />

se limita. Si ambas entradas están or<strong>de</strong>nadas por <strong>el</strong> atributo <strong>de</strong> join y la condición<br />

<strong>de</strong> join es un equi-join entonces se pue<strong>de</strong> utilizar <strong>el</strong> método <strong>de</strong> join por mezcla.<br />

Otra técnica alternativa es <strong>el</strong> join por encauzamiento que se presenta a<br />

continuación. El algoritmo supone que las tuplas <strong>de</strong> entrada <strong>de</strong> ambas r<strong>el</strong>aciones r<br />

y s están encauzadas. Las tuplas disponibles <strong>de</strong> ambas r<strong>el</strong>aciones se <strong>de</strong>jan listas<br />

<strong>para</strong> su procesamiento en una estructura <strong>de</strong> cola simple. Asimismo se generan<br />

marcas especiales llamadas Fin r y Fin s , que sirven como marcas <strong>de</strong> fin <strong>de</strong><br />

98


archivo y que se insertan en la cola <strong>de</strong>spués <strong>de</strong> que se hayan generado todas las<br />

tuplas <strong>de</strong> r y <strong>de</strong> s (respectivamente). Para una evaluación eficaz, se <strong>de</strong>berían<br />

construir los índices apropiados en las r<strong>el</strong>aciones r y s. Según se aña<strong>de</strong>n las tuplas<br />

a ambas r<strong>el</strong>aciones se <strong>de</strong>ben mantener los índices actualizados.<br />

El algoritmo <strong>de</strong> join encauzado es <strong>el</strong> siguiente :<br />

hechor = falso;<br />

hechos = falso;<br />

r = ∅ ;<br />

s = ∅ ;<br />

resultado = ∅ ;<br />

mientras not hechor or not hechos<br />

si la cola está vacía entonces esperar hasta que la cola no este vacía;<br />

t = primera entrada <strong>de</strong> la cola;<br />

si t = Finr entonces<br />

sino<br />

fin si<br />

fin mientras<br />

hechor = verda<strong>de</strong>ro;<br />

si t = Fins entonces<br />

sino<br />

fin si<br />

hechos = verda<strong>de</strong>ro;<br />

si t es <strong>de</strong> la entrada r entonces<br />

sino<br />

fin si<br />

r = r U {t};<br />

resultado = resultado U ({t} s);<br />

s = s U {t};<br />

resultado = resultado U (r {t});<br />

Algoritmo 5-5 - Join encauzado.<br />

99


5.4.4. Transformación <strong>de</strong> expresiones r<strong>el</strong>acionales.<br />

100<br />

Hasta ahora se han estudiado algoritmos <strong>para</strong> evaluar extensiones <strong>de</strong><br />

operaciones <strong>de</strong>l álgebra r<strong>el</strong>acional y se han estimado sus costos. Dado que una<br />

consulta se pue<strong>de</strong> evaluar <strong>de</strong> distintas maneras y por lo tanto con distintos costos<br />

estimados, este apartado consi<strong>de</strong>rará formas alternativas y equivalentes a sus<br />

expresiones.<br />

5.4.4.1. Equivalencia <strong>de</strong> expresiones.<br />

Cada implementación <strong>de</strong> base <strong>de</strong> datos tiene su forma <strong>de</strong> representación<br />

interna <strong>de</strong> <strong>consultas</strong> in<strong>de</strong>pendientes <strong>de</strong>l <strong>lenguaje</strong> <strong>de</strong> <strong>consultas</strong> utilizado. La<br />

representación interna <strong>de</strong>be cumplir con la característica <strong>de</strong> ser r<strong>el</strong>acionalmente<br />

completo, es por eso que comúnmente los motores <strong>de</strong> BD <strong>el</strong>igen la<br />

representación <strong>de</strong>l álgebra r<strong>el</strong>acional en forma <strong>de</strong> árbol sintáctico abstracto <strong>para</strong><br />

su representación interna.<br />

Dada una expresión <strong>de</strong>l álgebra r<strong>el</strong>acional, es trabajo <strong>de</strong>l optimizador<br />

alcanzar un plan <strong>de</strong> evaluación que calcule <strong>el</strong> mismo resultado que la expresión<br />

dada pero <strong>de</strong> la manera menos costosa <strong>de</strong> generar. Para encontrar este plan <strong>de</strong><br />

evaluación <strong>el</strong> optimizador necesita generar planes alternativos que produzcan <strong>el</strong><br />

mismo resultado que la expresión dada y <strong>el</strong>egir <strong>el</strong> más económico <strong>de</strong> <strong>el</strong>los. <strong>para</strong><br />

implementar este paso <strong>el</strong> optimizador <strong>de</strong>be generar expresiones que sean<br />

equivalente a la expresión dada por medio <strong>de</strong>l uso <strong>de</strong> las reglas <strong>de</strong> equivalencia<br />

que se explican a continuación.


5.4.4.2. Reglas <strong>de</strong> equivalencia.<br />

101<br />

Una regla <strong>de</strong> equivalencia dice que las expresiones <strong>de</strong> dos formas son<br />

equivalentes, por lo tanto se pue<strong>de</strong> transformar una en la otra mientras se<br />

preserva la equivalencia. Se entien<strong>de</strong> como preservar la equivalencia al hecho <strong>de</strong><br />

que las r<strong>el</strong>aciones generadas por ambas expresiones tienen <strong>el</strong> mismo conjunto <strong>de</strong><br />

atributos y contienen <strong>el</strong> mismo conjunto <strong>de</strong> tuplas.<br />

Formalmente se dice que se representa una expresión en su forma<br />

canónica.<br />

La noción <strong>de</strong> forma canónica es central a muchos brazos <strong>de</strong> la matemática<br />

y otras disciplinas r<strong>el</strong>acionadas. Esta pue<strong>de</strong> ser <strong>de</strong>finida como sigue:<br />

Dado un conjunto <strong>de</strong> Q objetos (digamos <strong>consultas</strong>) y una noción <strong>de</strong><br />

equivalencias entre objetos (digamos, la noción <strong>de</strong> que q1 y q2 son equivalentes<br />

si y sólo si <strong>el</strong>las producen <strong>el</strong> mismo resultado), un subconjunto C <strong>de</strong> Q se dice la<br />

forma canónica <strong>de</strong> Q (bajo la <strong>de</strong>finición <strong>de</strong> equivalencia expuesta anteriormente) si<br />

y sólo si cada objeto q en Q es equivalente a sólo un objeto c en C. El objeto c es<br />

llamado la forma canónica <strong>de</strong> <strong>el</strong> objeto q. Todas las propieda<strong>de</strong>s <strong>de</strong> interés que se<br />

aplican al objeto q también se aplican a su forma canónica c; por lo tanto es<br />

suficiente estudiar sólo <strong>el</strong> pequeño conjunto <strong>de</strong> formas canónicas C y no <strong>el</strong><br />

conjunto Q con <strong>el</strong> fin <strong>de</strong> probar una variedad <strong>de</strong> resultados.<br />

las reglas <strong>de</strong> equivalencia <strong>para</strong> llevar la expresión r<strong>el</strong>acional a una<br />

equivalente son:


1. Cascada <strong>de</strong> proyecciones:<br />

Π<br />

2. Cascada <strong>de</strong> s<strong>el</strong>ecciones:<br />

L1<br />

3. Conmutación <strong>de</strong> s<strong>el</strong>ecciones:<br />

( Π L2<br />

(...( Π Ln ( E))...)) = Π L1(<br />

E)<br />

σ θ1<br />

∧ σ θ 2(<br />

E) = σ θ1(<br />

σ θ 2(<br />

E))<br />

σ θ1(<br />

σ θ 2(<br />

E)) = σ θ 2(<br />

σ θ1(<br />

E))<br />

4. Conmutación <strong>de</strong> s<strong>el</strong>ección y proyección.<br />

5. Conmutación <strong>de</strong>l Join.<br />

Π L θ E θ L<br />

( σ ( )) = σ ( Π ( E))<br />

E = E<br />

E<br />

E1 θ 2 2 θ<br />

1<br />

102


6. Asociatividad <strong>de</strong>l Join Natural.<br />

caso1.<br />

(E )<br />

1<br />

E = E (E 2 E 3)<br />

E2 3 1<br />

caso 2. θ 2 involucra sólo atributos <strong>de</strong> 2 E y E 3 .<br />

(E )<br />

1<br />

θ1 E2<br />

θ 2∧θ<br />

3 E 3 = E1<br />

θ1 ∧ θ 3 (E2<br />

7. Distributividad <strong>de</strong> la s<strong>el</strong>ección con respecto al join.<br />

E 2<br />

caso 1. θ 0 involucra sólo atributos <strong>de</strong> E 1.<br />

σ θ 0(E 1 θ E2 ) σ θ 0(<br />

E1)<br />

= θ E2<br />

θ 2 E3)<br />

103<br />

caso 2. θ 1 involucra sólo atributos <strong>de</strong> 1 E y θ 2 involucra sólo atributos <strong>de</strong><br />

σ θ1∧<br />

θ 2(<br />

E<br />

θ E2 ) θ1<br />

1<br />

= ( σ ( E )) ( ))<br />

8. Distributividad <strong>de</strong> la proyección con respecto al join.<br />

θ ( σ θ 2 E2<br />

Si 1 L y 2 L son los atributos <strong>de</strong> 1 E y E2 respectivamente.<br />

Π (E = ( Π ( E ))<br />

L1 UL<br />

2<br />

1<br />

θ E2 ) L1<br />

1<br />

θ<br />

( Π L2<br />

( E2<br />

))


9. Conmutatividad <strong>de</strong> la unión y la intersección.<br />

E U E = E U E<br />

1<br />

1<br />

2<br />

E I E = E I E<br />

La diferencia <strong>de</strong> conjuntos no es conmutativa.<br />

10. Asociatividad <strong>de</strong> la unión e intersección.<br />

1<br />

2<br />

2<br />

( E1<br />

U E2<br />

) U E3<br />

= E1<br />

U ( E2<br />

U E3)<br />

( E I E ) I E = E I ( E I E )<br />

3<br />

2<br />

2<br />

1<br />

1<br />

1<br />

2<br />

3<br />

104<br />

11. Distributividad <strong>de</strong> la s<strong>el</strong>ección con respecto a la unión, intersección y<br />

diferencia.<br />

σ ( E U E ) = σ ( E ) U σ ( E )<br />

θ<br />

1<br />

1<br />

1<br />

2<br />

σ ( E I E ) = σ ( E ) I σ ( E )<br />

θ<br />

2<br />

2<br />

1<br />

1<br />

σ ( E − E ) = σ ( E ) − σ ( E ) = σ ( E ) − E<br />

θ<br />

12. Distributividad <strong>de</strong> la proyección con respecto a la unión.<br />

Ejemplo:<br />

θ<br />

θ<br />

θ<br />

1<br />

∏ L ( E1 U E2<br />

) = ( ∏ L ( E2<br />

)) U ( ∏ L ( E1))<br />

Tabla 5-3 - Reglas <strong>de</strong> equivalencia <strong>para</strong> expresiones r<strong>el</strong>acionales.<br />

θ<br />

θ<br />

θ<br />

2<br />

2<br />

2<br />

θ<br />

1<br />

2


105<br />

Supóngase que lo que se <strong>de</strong>sea es notificar a todos los dueños <strong>de</strong><br />

vehículos <strong>de</strong>l año, que estén siendo conducidos por los choferes con menos<br />

experiencia (supóngase un año o menos); la expresión r<strong>el</strong>acional sería :<br />

Π σ (( Dueños Moviles ) Choferes )<br />

Dueño . nombre ( Moviles.<br />

año=<br />

2001∧Choferes.<br />

Fecha _ licencia _ <strong>de</strong>s<strong>de</strong>><br />

Fecha()<br />

−1_<br />

año<br />

Se pue<strong>de</strong> utilizar la regla 6.1 con <strong>el</strong> fin <strong>de</strong> asociar <strong>el</strong> Join.<br />

Π σ ( Dueños ( Moviles Choferes ))<br />

Dueño . nombre ( Moviles.<br />

año=<br />

2001∧Choferes.<br />

Fecha _ licencia _ <strong>de</strong>s<strong>de</strong>><br />

Fecha()<br />

−1_<br />

año<br />

Aplicando la regla 5 se pue<strong>de</strong> conmutar <strong>el</strong> Join.<br />

Π σ (( Moviles Choferes ) Dueños )<br />

Dueño . nombre ( Moviles.<br />

año=<br />

2001∧Choferes.<br />

Fecha _ licencia _ <strong>de</strong>s<strong>de</strong>><br />

Fecha()<br />

−1_<br />

año<br />

Luego se aplica la regla 7.1 con <strong>el</strong> fin <strong>de</strong> distribuir la s<strong>el</strong>ección sobre <strong>el</strong> join.<br />

Π σ ( Moviles Choferes )) Dueños )<br />

Dueño . nombre (( Moviles.<br />

año=<br />

2001∧Choferes.<br />

Fecha _ licencia _ <strong>de</strong>s<strong>de</strong>><br />

Fecha()<br />

−1_<br />

año<br />

Aplicando la regla 7.2 se obtiene :<br />

Π σ ( Moviles))<br />

σ ( Choferes)))<br />

Dueños<br />

)<br />

Dueño . nombre ((( año=<br />

2001<br />

( Fecha _ licencia _ <strong>de</strong>s<strong>de</strong>><br />

Fecha()<br />

−1_<br />

año


106<br />

Las siguientes figuras muestran la expresión inicial y la final en una<br />

estructura <strong>de</strong> árbol sintáctico.


107<br />

Así, los optimizadores generan <strong>de</strong> manera sistemática expresiones<br />

equivalentes a la consulta dada. El proceso se entien<strong>de</strong> como sigue: dada una<br />

expresión, se analiza cada subexpresión <strong>para</strong> saber si se pue<strong>de</strong> aplicar una regla<br />

<strong>de</strong> equivalencia. De ser así se genera una nueva expresión don<strong>de</strong> la subexpresión<br />

que concuerda con una regla <strong>de</strong> equivalencia se reemplaza por su equivalente.<br />

Este proceso continúa hasta que no se pue<strong>de</strong>n generar más expresiones nuevas.<br />

Una optimización en términos <strong>de</strong> espacio se pue<strong>de</strong> lograr como sigue. Si se<br />

genera una expresión E1 <strong>de</strong> una expresión E2 mediante una regla <strong>de</strong><br />

equivalencia, entonces E1 y E2 son equivalentes en su estructura y por lo tanto<br />

sus subexpresiones son idénticas. Las técnicas <strong>de</strong> representación <strong>de</strong> expresiones<br />

que permiten a ambas expresiones apuntar a la subexpresión compartida pue<strong>de</strong>n<br />

reducir <strong>el</strong> espacio <strong>de</strong> búsqueda significativamente.<br />

5.5. Or<strong>de</strong>nes <strong>de</strong> Join.<br />

En los sistemas <strong>de</strong> base <strong>de</strong> datos r<strong>el</strong>acionales tradicionales raramente se<br />

encuentra una consulta que involucre más <strong>de</strong> 5 tablas, <strong>de</strong> este modo, <strong>el</strong> cálculo <strong>de</strong><br />

un or<strong>de</strong>n <strong>de</strong> Join óptimo con <strong>el</strong> menor costo <strong>de</strong> evaluación por medio <strong>de</strong> una<br />

búsqueda exhaustiva es perfectamente posible. Sin embargo, cuando esta<br />

consulta involucra 8 o más tablas <strong>el</strong> problema no se pue<strong>de</strong> <strong>de</strong>terminar <strong>de</strong> esta<br />

forma. Por lo tanto lo que se espera son algoritmos que calculen la mejor<br />

aproximación a la solución. Estos algoritmos pue<strong>de</strong>n ser se<strong>para</strong>dos en dos clases.<br />

1. Heurísticas: Construyen un plan <strong>de</strong> evaluación paso a paso <strong>de</strong> acuerdo a<br />

ciertos criterios pre<strong>de</strong>finidos.


108<br />

2. Aleatorios: Realizan una especie <strong>de</strong> “caminata aleatoria” a través <strong>de</strong>l<br />

espacio <strong>de</strong> todas las posibles soluciones.<br />

Generalmente <strong>el</strong> espacio <strong>de</strong> soluciones se <strong>de</strong>fine como <strong>el</strong> conjunto <strong>de</strong> todos<br />

los árboles que calculan <strong>el</strong> resultado <strong>de</strong>l Join y que contienen cada r<strong>el</strong>ación base<br />

exactamente una vez. Las hojas <strong>de</strong> estos árboles consisten en las r<strong>el</strong>aciones<br />

base, mientras que los nodos internos correspon<strong>de</strong>n a los resultados <strong>de</strong> Join <strong>de</strong><br />

los correspondientes hijos. Dado que la operación Join es conmutativa y asociativa<br />

(ver equivalencia <strong>de</strong> expresiones algebraicas en la sección 5.4.4.1) <strong>el</strong> número <strong>de</strong><br />

posibles árboles <strong>de</strong> proceso se incrementa rápidamente a medida que se<br />

incrementa <strong>el</strong> número <strong>de</strong> r<strong>el</strong>aciones bases que participan en <strong>el</strong> Join. Existe un<br />

subconjunto <strong>de</strong> este espacio <strong>de</strong> soluciones, comúnmente llamado “árboles en<br />

profundidad por la izquierda” que ha sido <strong>de</strong> especial interés en los estudios <strong>de</strong><br />

optimizadores <strong>de</strong> <strong>consultas</strong> [Steinbrunn93].<br />

Árboles en profundidad por la izquierda.<br />

Este subconjunto <strong>de</strong> soluciones consiste en todos los árboles don<strong>de</strong> la<br />

r<strong>el</strong>ación interna <strong>de</strong> cada Join es una r<strong>el</strong>ación base. Para un número fijo <strong>de</strong><br />

r<strong>el</strong>aciones base, la especificación <strong>de</strong> profundidad por la izquierda no <strong>de</strong>ja ningún<br />

grado <strong>de</strong> libertad concerniente a la forma <strong>de</strong>l árbol, sin embargo, se sabe a ciencia<br />

cierta que existen n! formas <strong>de</strong> agrupar n r<strong>el</strong>aciones base en las hojas <strong>de</strong>l árbol<br />

[Steinbrunn93].<br />

Árboles <strong>de</strong> disposición General.<br />

La solución en este espacio no es restringida <strong>de</strong> ninguna manera, dado que<br />

la forma <strong>de</strong> todos los posibles árboles pue<strong>de</strong> ser arbitraria , la cardinalidad <strong>de</strong> este


109<br />

⎛2(<br />

n −1)<br />

⎞<br />

conjunto es mucho más alta: <strong>para</strong> n r<strong>el</strong>aciones base existen ⎜ ⎟(<br />

n −1)!<br />

⎝ n −1<br />

⎠<br />

soluciones diferentes.<br />

El problema <strong>de</strong> encontrar un buen or<strong>de</strong>n <strong>de</strong> anidamiento pue<strong>de</strong> ser<br />

abordado <strong>de</strong> diferentes formas:<br />

1. Algoritmos Determinísticos. Cada algoritmo en esta clase construye una<br />

solución paso a paso <strong>de</strong> una forma <strong>de</strong>terminística, ya sea aplicando<br />

heurísticas o por medio <strong>de</strong> una búsqueda exhaustiva.<br />

2. Algoritmos Aleatorios. Para estos algoritmos se <strong>de</strong>fine un conjunto <strong>de</strong><br />

movimientos.<br />

Estos movimientos constituyen un “margen” entre las diferentes soluciones<br />

<strong>de</strong>l espacio <strong>de</strong> soluciones. Dos soluciones son conectadas por un “margen”<br />

si y sólo si, <strong>el</strong>las pue<strong>de</strong>n ser transformadas una en la otra por medio <strong>de</strong> un<br />

sólo movimiento. Cada uno <strong>de</strong> estos algoritmos realizan una “caminata<br />

aleatoria” a lo largo <strong>de</strong> los “márgenes” <strong>de</strong> acuerdo a ciertas reglas,<br />

terminando ya sea si no existen más movimientos a realizar o si se ha<br />

excedido un lapso <strong>de</strong> tiempo pre<strong>de</strong>terminado. La mejor solución encontrada<br />

hasta ese momento es la solución <strong>el</strong>egida.<br />

3. Algoritmos Genéticos. Estos algoritmos hacen uso <strong>de</strong> la estrategia<br />

aleatoria, muy similar a la evolución biológica. La i<strong>de</strong>a básica es comenzar<br />

con una población base y generar <strong>de</strong>scen<strong>de</strong>ncia por medio <strong>de</strong> cruces<br />

aleatorios, <strong>el</strong> más “digno” <strong>de</strong> los miembros <strong>de</strong> la población (<strong>de</strong> acuerdo a<br />

una función <strong>de</strong> costo) sobrevive a la s<strong>el</strong>ección y la siguiente generación<br />

estará basada en él. El algoritmo terminará ya sea si no hay mayor


110<br />

perfeccionamiento o <strong>de</strong>spués <strong>de</strong> un <strong>de</strong>terminado número <strong>de</strong> generaciones.<br />

El miembro más digno <strong>de</strong> la población actual en <strong>el</strong> momento <strong>de</strong> terminar <strong>el</strong><br />

algoritmo será la solución <strong>el</strong>egida.<br />

4. Algoritmos híbridos. Los algoritmos híbridos combinan las estrategias <strong>de</strong> los<br />

algoritmos <strong>de</strong>terminísticos y <strong>de</strong> los aleatorios. La i<strong>de</strong>a es que la solución<br />

obtenida por medio <strong>de</strong> algoritmos <strong>de</strong>terminísticos sirva como punto <strong>de</strong><br />

partida <strong>para</strong> los algoritmos aleatorios o como población base <strong>para</strong> los<br />

algoritmos genéticos.<br />

5.5.1. Algoritmos Determinísticos.<br />

5.5.1.1. S<strong>el</strong>ectividad mínima.<br />

Las buenas soluciones comúnmente se caracteriza porque los resultados<br />

intermedios tienen una pequeña cardinalidad. La heurística <strong>de</strong> s<strong>el</strong>ectividad mínima<br />

construye un árbol <strong>de</strong> profundidad por la izquierda paso a paso mientras trata <strong>de</strong><br />

mantener r<strong>el</strong>aciones intermedias tan pequeñas como sea posible. El factor <strong>de</strong><br />

s<strong>el</strong>ectividad s <strong>de</strong> R1 R2 se <strong>de</strong>fine como:


111<br />

Al principio, <strong>el</strong> conjunto <strong>de</strong> r<strong>el</strong>aciones a ser unidas se divi<strong>de</strong>n en dos<br />

subconjuntos. El conjunto <strong>de</strong> r<strong>el</strong>aciones ya incorporados en <strong>el</strong> resultado intermedio<br />

<strong>de</strong>notado como Rusados y <strong>el</strong> conjunto <strong>de</strong> r<strong>el</strong>aciones que aun quedan por unir con <strong>el</strong><br />

resultado intermedio que se <strong>de</strong>nota como Rrestantes. Entonces, en cada paso <strong>de</strong> <strong>el</strong><br />

algoritmo la R<strong>el</strong>ación Ri ∈ Rrestantes con <strong>el</strong> menor factor <strong>de</strong> s<strong>el</strong>ectividad<br />

Rusados .<br />

será mezclada con <strong>el</strong> resultado intermedio y será movida <strong>de</strong>s<strong>de</strong> Rrestantes a<br />

5.5.1.2. Heurística Top-Down.<br />

El principio <strong>de</strong> esta técnica esta basado en la observación <strong>de</strong> que los<br />

últimos Join son los más importantes <strong>para</strong> la expresión en términos <strong>de</strong> costo,<br />

simplemente porque los resultados intermedios tien<strong>de</strong>n a ser algo más largos<br />

hacia <strong>el</strong> fin <strong>de</strong> la evaluación. Así, esta estrategia s<strong>el</strong>ecciona las r<strong>el</strong>aciones <strong>de</strong>l<br />

conjunto que pue<strong>de</strong>n ser mezcladas con menor costo con <strong>el</strong> resto <strong>de</strong> las<br />

r<strong>el</strong>aciones. Esta estrategia se aplicará repetidamente hasta que no que<strong>de</strong>n<br />

r<strong>el</strong>aciones disponibles.<br />

Ejemplo: suponiendo que existen 6 tablas (O, B, A, P, W, C) a ser unidas,<br />

la primera r<strong>el</strong>ación en <strong>el</strong> or<strong>de</strong>n será la que tiene <strong>el</strong> menor costo si se une con <strong>el</strong><br />

resto, suponiendo un costo h como medida mínima, <strong>el</strong> costo <strong>de</strong> cada una <strong>de</strong> las 6<br />

combinaciones sería:


C(OBAPW C) = h<br />

C(CBAPW O) = 35h<br />

C(COAPW B) = 5h<br />

C(COBPW A) = h<br />

C(COBAW P) = h<br />

C(COBAP W) = h<br />

112<br />

El costo <strong>para</strong> C, A, P y W es <strong>el</strong> mismo, por lo tanto se escogerá<br />

arbitrariamente C, las 5 alternativas restantes <strong>de</strong>l segundo paso son:<br />

C(BAPW O) = 7h<br />

C(OAPW B) = 5h<br />

C(OBPW A) = h<br />

C(OBAW P) = h<br />

C(OBAP W) = h<br />

Al escoger A como la siguiente r<strong>el</strong>ación, <strong>el</strong> tercer paso será:<br />

El cuarto paso luego <strong>de</strong> escoger P:<br />

C(BPW O) = 7h<br />

C(OPW B) = 5h<br />

C(OBW P) = h<br />

C(OBP W) = h<br />

C(BW O) = 7h<br />

C(OW B) = 5h<br />

C(OB W) = h


113<br />

Luego <strong>de</strong> escoger W como la cuarta r<strong>el</strong>ación en <strong>el</strong> or<strong>de</strong>n las alternativas<br />

restantes son:<br />

Así, <strong>el</strong> or<strong>de</strong>n final <strong>de</strong> Join es :<br />

C(B O) = 7h<br />

C(O B) = 5h<br />

((((O B) W ) P) A) C<br />

Con un costo total <strong>de</strong> : (5+1+1+1+1) = 9h<br />

5.5.2. Algoritmos Aleatorios.<br />

Los Algoritmos aleatorios ven soluciones como puntos en un espacio <strong>de</strong><br />

soluciones y conecta estos puntos por márgenes que se <strong>de</strong>finen como un conjunto<br />

<strong>de</strong> movimientos. Este tipo <strong>de</strong> algoritmos realizan una suerte <strong>de</strong> caminata aleatoria<br />

a través <strong>de</strong>l espacio <strong>de</strong> soluciones a lo largo <strong>de</strong> los márgenes <strong>de</strong>finidos como<br />

movimientos. El tipo <strong>de</strong> movimientos que son consi<strong>de</strong>rados <strong>de</strong>pen<strong>de</strong>rá mucho <strong>de</strong>l<br />

tipo <strong>de</strong> espacio <strong>de</strong> soluciones. Si lo que se <strong>de</strong>sea son árboles <strong>de</strong> profundidad por<br />

la izquierda, cada solución sólo se pue<strong>de</strong> representar por medio <strong>de</strong> una lista<br />

or<strong>de</strong>nada <strong>de</strong> r<strong>el</strong>aciones que participan en <strong>el</strong> Join.<br />

5.5.2.1. Caminata aleatoria.<br />

El algoritmo aleatorio más simple realiza una caminata a través <strong>de</strong>l espacio<br />

<strong>de</strong> soluciones empezando en un punto s<strong>el</strong>eccionado aleatoriamente. En cada


114<br />

paso <strong>de</strong>l algoritmo se realiza un movimiento aleatorio y si <strong>el</strong> nuevo punto<br />

constituye una mejor solución (en términos <strong>de</strong> la función <strong>de</strong> costo <strong>el</strong>egida) este se<br />

almacenará como <strong>el</strong> nuevo resultado. El algoritmo terminará <strong>de</strong>spués <strong>de</strong> un<br />

pre<strong>de</strong>terminado número <strong>de</strong> movimientos y la mejor solución encontrada hasta <strong>el</strong><br />

momento será la solución <strong>el</strong>egida como resultado. En principio, este algoritmo<br />

traza una muestra aleatoria <strong>de</strong>s<strong>de</strong> <strong>el</strong> conjunto <strong>de</strong> todas las soluciones posibles y<br />

entrega la mejor solución <strong>de</strong>s<strong>de</strong> esta muestra. El rendimiento <strong>de</strong> este algoritmo<br />

<strong>de</strong>pen<strong>de</strong> fuertemente <strong>de</strong>l factor <strong>de</strong> buenas / malas soluciones y <strong>de</strong>l tamaño <strong>de</strong> la<br />

muestra <strong>el</strong>egida. Sin embargo, es obvio que esta estrategia es una perdida <strong>de</strong><br />

recursos dado que sólo cubre una pequeña área en la proximidad <strong>de</strong>l punto <strong>de</strong><br />

partida y no se hace nunca un intento siquiera <strong>de</strong> encontrar un mínimo local.<br />

5.5.2.2. Mejora Iterativa.<br />

Un acercamiento más sofisticado es <strong>el</strong> algoritmo <strong>de</strong> mejora iterativa<br />

[Swami88]. Luego <strong>de</strong> s<strong>el</strong>eccionar una punto <strong>de</strong> partida aleatorio <strong>el</strong> algoritmo busca<br />

un punto <strong>de</strong> costo mínimo. comenzando en <strong>el</strong> punto <strong>de</strong> partida, se <strong>el</strong>ige al azar un<br />

vecindario próximo (esto es, puntos que puedan ser alcanzados por exactamente<br />

un movimiento), si <strong>el</strong> costo asociados a los vecinos es menor que <strong>el</strong> costo <strong>de</strong>l<br />

punto actual entonces <strong>el</strong> movimiento se lleva a cabo y se busca un nuevo vecino<br />

con un menor costo. Un punto se <strong>de</strong>finirá como mínimo local si no se han<br />

encontrado vecinos con menor costo <strong>de</strong>spués <strong>de</strong> un cierto número <strong>de</strong> intentos.<br />

Este procedimiento se repite hasta que se hayan procesado un número<br />

pre<strong>de</strong>terminado <strong>de</strong> puntos <strong>de</strong> partida o se haya excedido un límite <strong>de</strong> tiempo. El<br />

menor <strong>de</strong> los mínimos locales encontrados será <strong>el</strong> resultado.


5.5.2.3. Simulación <strong>de</strong> cocción.<br />

115<br />

El algoritmo <strong>de</strong> mejora iterativa sufre <strong>de</strong> un gran inconveniente: dado que<br />

los movimientos son aceptados sólo si mejoran <strong>el</strong> resultado obtenido hasta <strong>el</strong><br />

momento, es posible que aún con un alto número <strong>de</strong> puntos <strong>de</strong> partida <strong>el</strong> resultado<br />

final sea inaceptable. Este será <strong>el</strong> caso cuando <strong>el</strong> espacio <strong>de</strong> solución no muestra<br />

un mínimo global, sino que una gran número <strong>de</strong> mínimos locales <strong>de</strong> alto costo. En<br />

este caso <strong>el</strong> algoritmo pue<strong>de</strong> quedar fácilmente atrapado en uno <strong>de</strong> estos mínimos<br />

locales.<br />

El algoritmo <strong>de</strong> Simulación <strong>de</strong> cocción es un refinamiento <strong>de</strong> la Mejora<br />

Iterativa que quita esta restricción. En <strong>el</strong> algoritmo <strong>de</strong> Simulación <strong>de</strong> cocción se<br />

pue<strong>de</strong> efectuar un movimiento aún si los puntos <strong>de</strong>l vecindario son <strong>de</strong> costos altos.<br />

Así este algoritmo no queda tan fácilmente atrapado en mínimos locales como <strong>el</strong><br />

algoritmo <strong>de</strong> Mejora Iterativa.<br />

El nombre <strong>de</strong> este algoritmo viene <strong>de</strong>l estudio <strong>de</strong>l proceso <strong>de</strong> cocción <strong>de</strong> los<br />

cristales, en este proceso natural <strong>el</strong> sistema eventualmente alcanza un estado <strong>de</strong><br />

mínima energía que se r<strong>el</strong>aciona directamente con la temperatura que toman los<br />

cristales.<br />

La siguiente figura muestra este comportamiento. Mientras que <strong>el</strong> Algoritmo<br />

<strong>de</strong> Mejora Iterativa se <strong>de</strong>tiene en <strong>el</strong> primer mínimo local que encuentra, <strong>el</strong><br />

algoritmo <strong>de</strong> Simulación <strong>de</strong> cocción se salta la barrera <strong>de</strong> costo que se<strong>para</strong> este<br />

punto <strong>de</strong>l punto mínimo global, dado que este algoritmo siempre acepta<br />

movimientos que lleven a una estado <strong>de</strong> menor costo, mientras que los<br />

movimientos que incrementan <strong>el</strong> costo se aceptan con una probabilidad que<br />

<strong>de</strong>pen<strong>de</strong>rá <strong>de</strong> la temperatura y <strong>de</strong> la diferencia entre <strong>el</strong> estado <strong>de</strong> costo actual y <strong>el</strong><br />

nuevo.


Figura 5-1 - Comportamiento <strong>de</strong>l Algoritmo <strong>de</strong> Simulación <strong>de</strong> Cocción<br />

116<br />

En cualquier caso, <strong>el</strong> comportamiento exacto <strong>de</strong>l algoritmo está<br />

<strong>de</strong>terminado por parámetros tales como la temperatura inicial, los pasos <strong>de</strong><br />

reducción <strong>de</strong> temperatura y la condición <strong>de</strong> fin. La literatura al respecto presenta<br />

distintas variantes que no viene al caso estudiarlas acá. Para encontrar<br />

referencias se recomienda consultar [Steinbrunn93].


5.5.3. Algoritmos Genéticos.<br />

117<br />

Los Algoritmos genéticos están diseñados <strong>para</strong> simular <strong>el</strong> proceso natural<br />

<strong>de</strong> evolución. Al igual que en la naturaleza, don<strong>de</strong> <strong>el</strong> miembro más digno <strong>de</strong> una<br />

población es <strong>el</strong> que tiene la mayor probabilidad <strong>de</strong> sobrevivir y <strong>de</strong> heredar sus<br />

características a su <strong>de</strong>scen<strong>de</strong>ncia, los algoritmos genéticos propagan soluciones<br />

<strong>para</strong> un <strong>de</strong>terminado problema <strong>de</strong> generación en generación, combinándolos <strong>para</strong><br />

alcanzar mejoras. A continuación se presenta una breve terminología, <strong>para</strong> una<br />

compresión más <strong>de</strong>tallada se recomienda consultar [Steinbrunn93].<br />

Una <strong>de</strong> las características más importantes <strong>de</strong> los algoritmos genéticos es<br />

que trabajan sobre un conjunto <strong>de</strong> soluciones (población). Las soluciones son<br />

representadas como ca<strong>de</strong>nas <strong>de</strong> caracteres (cromosomas) compuestos <strong>de</strong><br />

caracteres (genes) que pue<strong>de</strong>n tomar diferentes valores. Por lo tanto <strong>el</strong> problema<br />

que soluciona un algoritmo genético tiene una solución representada como una<br />

ca<strong>de</strong>na <strong>de</strong> caracteres con una codificación apropiada.<br />

La “dignidad” <strong>de</strong> una solución se medirá <strong>de</strong> acuerdo a una función objetivo<br />

que <strong>de</strong>be ser minimizada o maximizada. Generalmente, en un algoritmo genético<br />

bien diseñado ya sea <strong>el</strong> índice <strong>de</strong> dignidad promedio como <strong>el</strong> <strong>de</strong> la mejor solución<br />

se <strong>de</strong>ben incrementar con cada nueva generación.


5.5.3.1. Algoritmo genético <strong>para</strong> la optimización <strong>de</strong> or<strong>de</strong>nes <strong>de</strong> Join.<br />

El principio <strong>de</strong> este algoritmo es <strong>el</strong> siguiente.<br />

118<br />

Primero, se genera una población aleatoria <strong>de</strong> ca<strong>de</strong>nas <strong>de</strong> caracteres, Esta<br />

será la generación “cero” <strong>de</strong> soluciones. Luego, cada generación se <strong>de</strong>termina<br />

como sigue.<br />

• Una fracción <strong>de</strong> los miembros más dignos <strong>de</strong> la población se propaga a la<br />

siguiente generación (Principio <strong>de</strong> s<strong>el</strong>ección).<br />

• Una fracción <strong>de</strong> los miembros más dignos <strong>de</strong> la población se combina<br />

generando <strong>de</strong>scen<strong>de</strong>ncia. (principio <strong>de</strong> combinación)<br />

• Una fracción <strong>de</strong> la población (no necesariamente la más digna) se altera <strong>de</strong><br />

forma aleatoria (Principio <strong>de</strong> Mutación)<br />

Estas fracciones son <strong>el</strong>egidas <strong>de</strong> modo que <strong>el</strong> número total <strong>de</strong> soluciones<br />

permanezca invariante.<br />

Este ciclo se itera hasta que la mejor solución en la población ha alcanzado<br />

la calidad <strong>de</strong>seada, se ha producido un número pre<strong>de</strong>terminado <strong>de</strong> generaciones<br />

o hasta que la mejora entre una generación y otra ha caído por <strong>de</strong>bajo <strong>de</strong> un cierto<br />

umbral pre<strong>de</strong>terminado.<br />

Antes <strong>de</strong> que se pueda aplicar un cierto algoritmo se <strong>de</strong>be <strong>el</strong>egir una<br />

codificación apropiada y una función objetivo. Para la optimización <strong>de</strong> or<strong>de</strong>nes <strong>de</strong><br />

join las soluciones son árboles ya sea <strong>de</strong> profundidad por la izquierda o <strong>de</strong>


119<br />

disposición general. La función objetivo es la evaluación <strong>de</strong> costo a ser<br />

minimizada.<br />

Una codificación <strong>para</strong> <strong>el</strong> caso <strong>de</strong> los árboles <strong>de</strong> profundidad por la izquierda<br />

pue<strong>de</strong> ser representada únicamente por medio <strong>de</strong> una lista or<strong>de</strong>nada <strong>de</strong> sus<br />

hojas.<br />

Por ejemplo:<br />

((((R1 R4) R3) R2) R5) produce la ca<strong>de</strong>na “14325”.<br />

Principio <strong>de</strong> S<strong>el</strong>ección.<br />

El operador <strong>de</strong> s<strong>el</strong>ección se utiliza <strong>para</strong> se<strong>para</strong>r buenas y malas soluciones<br />

<strong>de</strong> la población, la motivación <strong>de</strong> este ejercicio es <strong>el</strong> po<strong>de</strong>r remover <strong>de</strong>l espacio <strong>de</strong><br />

soluciones a las malas soluciones. En la Figura 5-2 se muestra un ejemplo <strong>de</strong><br />

s<strong>el</strong>ección. La población <strong>de</strong> muestra consiste <strong>de</strong> 4 soluciones, la función objetivo<br />

dice que <strong>el</strong> costo <strong>de</strong>be ser minimizado. El costo <strong>para</strong> cada una <strong>de</strong> la soluciones se<br />

lista en la tabla <strong>de</strong> la Figura 5-2. A cada solución se le asigna un sector en una<br />

ruleta <strong>de</strong> tamaño inversamente proporcional al costo. Al cabo <strong>de</strong> 4 vu<strong>el</strong>tas a la<br />

ruleta se obtienen los resultados que se muestran en la segunda tabla <strong>de</strong> la Figura<br />

5-2 don<strong>de</strong> la solución 4 se ha “extinguido <strong>de</strong>bido a falta <strong>de</strong> adaptación”.


Figura 5-2 - Ejemplo <strong>de</strong>l principio <strong>de</strong> s<strong>el</strong>ección <strong>para</strong> <strong>el</strong> algoritmo genético <strong>para</strong> la optimización <strong>de</strong> or<strong>de</strong>nes <strong>de</strong> Join<br />

120<br />

Este esquema se basa en <strong>el</strong> factor <strong>de</strong> “dignidad” <strong>de</strong> los miembros <strong>de</strong> la<br />

población. Mientras mejor se satisfaga la función objetivo más posibilida<strong>de</strong>s tiene<br />

en la ruleta.<br />

Principio <strong>de</strong> Combinación.<br />

El operador <strong>de</strong> combinación es un medio <strong>para</strong> combinar parcialmente las<br />

buenas soluciones con <strong>el</strong> fin <strong>de</strong> obtener un resultado superior. La realización <strong>de</strong><br />

una combinación <strong>de</strong>pen<strong>de</strong>rá fuertemente <strong>de</strong> la codificación escogida dado que, <strong>el</strong><br />

operador <strong>de</strong> combinación tiene que tener la certeza <strong>de</strong> que las características <strong>de</strong><br />

una codificación en particular no se han violado. Para <strong>el</strong> caso estándar <strong>de</strong> la


121<br />

codificación estudiada en los árboles <strong>de</strong> profundidad por la izquierda se utiliza <strong>el</strong><br />

operador <strong>de</strong> combinación llamado “Intercambio <strong>de</strong> subsecuencias”.<br />

Para cada uno <strong>de</strong> los dos padres se s<strong>el</strong>ecciona una subsecuencia aleatoria,<br />

esta secuencia se quita <strong>de</strong> la ca<strong>de</strong>na y <strong>el</strong> espacio <strong>de</strong>jado se reemplaza con los<br />

caracteres <strong>de</strong>l otro padre en or<strong>de</strong>n <strong>de</strong> proce<strong>de</strong>ncia.<br />

Figura 5-3 - Ejemplo <strong>de</strong>l principio <strong>de</strong> combinación <strong>para</strong> <strong>el</strong> algoritmo genético <strong>para</strong> la optimización <strong>de</strong> or<strong>de</strong>nes <strong>de</strong> Join<br />

En <strong>el</strong> ejemplo <strong>de</strong> la Figura 5-3 se s<strong>el</strong>ecciona la subsecuencia “532” <strong>de</strong> la<br />

ca<strong>de</strong>na “45321”, <strong>el</strong> primer caracter <strong>de</strong> su <strong>de</strong>scen<strong>de</strong>ncia permanece igual que su<br />

padre (4), <strong>el</strong> segundo caracter se toma <strong>de</strong>l primer caracter <strong>de</strong>l otro padre (3), <strong>el</strong><br />

segundo caracter <strong>de</strong>l otro padre no pue<strong>de</strong> se utilizado pues ya está presente (1),<br />

por lo tanto <strong>el</strong> tercer caracter <strong>de</strong> la <strong>de</strong>scen<strong>de</strong>ncia se sacará <strong>de</strong>l tercer caracter <strong>de</strong>l<br />

otro padre, continuando este proceso se llega a “43521”. El proceso <strong>de</strong> <strong>de</strong>terminar<br />

la segunda <strong>de</strong>scen<strong>de</strong>ncia <strong>de</strong> efectúa <strong>de</strong> igual forma.<br />

Principio <strong>de</strong> Mutación.<br />

El operador <strong>de</strong> mutación se utiliza <strong>para</strong> introducir características que no<br />

están presentes en ningún miembro <strong>de</strong> la población. La mutación se lleva a cabo<br />

por medio <strong>de</strong> la alteración aleatoria <strong>de</strong> una ca<strong>de</strong>na s<strong>el</strong>eccionada aleatoriamente.<br />

Una forma básica <strong>de</strong> mutación es <strong>el</strong> intercambio (swap) <strong>de</strong> 2 caracteres aleatorios<br />

<strong>de</strong>ntro <strong>de</strong> una ca<strong>de</strong>na.


122<br />

Debido al carácter <strong>de</strong> la mutación como algo poco <strong>de</strong>seado en un proceso<br />

evolutivo, este no <strong>de</strong>be ser aplicado sin control sobre una generación dado que<br />

pue<strong>de</strong> ser dañada severamente. Usualmente se realizan muy pocas mutaciones<br />

en una generación.


5.6. Elección <strong>de</strong> los planes <strong>de</strong> evaluación.<br />

123<br />

Un plan <strong>de</strong> evaluación <strong>de</strong>fine exactamente que algoritmo utilizar <strong>para</strong> cada<br />

operación y como coordinar la ejecución <strong>de</strong> las operaciones.<br />

La Figura 5-4 muestra un plan <strong>de</strong> evaluación <strong>para</strong> la expresión analizada en<br />

<strong>el</strong> ejemplo <strong>de</strong> la sección 5.4.4.2. Se hace la suposición respecto a algunos índices<br />

con <strong>el</strong> fin <strong>de</strong> lograr encauzamiento.<br />

Figura 5-4 - Un plan <strong>de</strong> evaluación <strong>de</strong> ejemplo


124<br />

Una forma <strong>de</strong> <strong>el</strong>egir los planes <strong>de</strong> evaluación es simplemente <strong>el</strong>egir <strong>para</strong><br />

cada operación <strong>el</strong> algoritmo más económico <strong>para</strong> luego <strong>el</strong>egir cualquier<br />

or<strong>de</strong>nación. Sin embargo, la <strong>el</strong>ección in<strong>de</strong>pendiente <strong>de</strong>l algoritmo más económico<br />

no es necesariamente la mejor <strong>el</strong>ección. Por ejemplo, en una operación <strong>de</strong> Join,<br />

bajo ciertas circunstancias pue<strong>de</strong> ser más costosa con <strong>el</strong> algoritmo <strong>de</strong> join por<br />

mezcla <strong>de</strong> lo que podría ser con un algoritmo <strong>de</strong> Join por asociación. Sin embargo,<br />

la primera alternativa pue<strong>de</strong> producir una salida or<strong>de</strong>nada que pue<strong>de</strong> ayudar a la<br />

evaluación <strong>de</strong> una operación posterior (como una <strong>el</strong>iminación <strong>de</strong> duplicados o la<br />

entrada <strong>para</strong> otro join por mezcla) por lo tanto, <strong>para</strong> <strong>el</strong>egir <strong>el</strong> mejor algoritmo<br />

genérico habrá que consi<strong>de</strong>rar incluso los algoritmos no óptimos <strong>de</strong> las<br />

operaciones individuales.<br />

Como en <strong>el</strong> caso <strong>de</strong> las expresiones equivalentes, se pue<strong>de</strong>n utilizar reglas<br />

parecidas <strong>para</strong> <strong>de</strong>finir los posibles algoritmos <strong>de</strong> una operación, incluyendo aquí<br />

las <strong>de</strong>cisiones <strong>de</strong> encauzamiento <strong>de</strong> esta operación con otra a evaluar.<br />

Existen 2 gran<strong>de</strong>s aproximaciones <strong>para</strong> <strong>el</strong>egir <strong>el</strong> mejor plan <strong>de</strong> evaluación<br />

<strong>de</strong> una consulta. La primera examina todos los planes y <strong>el</strong>ige <strong>el</strong> mejor basándose<br />

en <strong>el</strong> costo estimado. La segunda aproximación utiliza heurísticas.<br />

La mayoría <strong>de</strong> los optimizadores actuales incorporan <strong>el</strong>ementos <strong>de</strong> ambas<br />

aproximaciones en la <strong>el</strong>ección <strong>de</strong> los planes <strong>de</strong> ejecución.<br />

5.6.1. Heurísticas.<br />

Aunque sea <strong>para</strong>dojal, <strong>el</strong> mayor inconveniente <strong>de</strong> la optimización por costos<br />

es precisamente <strong>el</strong> cálculo <strong>de</strong>l costo, <strong>para</strong> aliviar este cálculo muchos


125<br />

optimizadores utilizan heurísticas que ayudan a reducir <strong>el</strong> número <strong>de</strong> <strong>el</strong>ecciones a<br />

realizar en la optimización por costos.<br />

Algunas <strong>de</strong> estas son utilizadas y aceptadas por la mayoría <strong>de</strong> los<br />

optimizadores, a <strong>de</strong>cir :<br />

• Realizar las s<strong>el</strong>ecciones tan pronto como sea posible. Un optimizador<br />

basado sólo en heurísticas <strong>de</strong>bería aplicar esta regla al pie <strong>de</strong> la letra. Sin<br />

embargo, un poco <strong>de</strong> estudio indica que existe la posibilidad <strong>de</strong> que <strong>el</strong> uso<br />

<strong>de</strong> esta regla no ayu<strong>de</strong> siempre a reducir <strong>el</strong> costo. Como ejemplo <strong>de</strong> lo<br />

anterior, considérese la expresión σ ( r | x | s)<br />

don<strong>de</strong> la condición θ se<br />

refiere solamente a los atributos <strong>de</strong> s. Supóngase a<strong>de</strong>más que r es<br />

extremadamente pequeño, y que existe un índice en los atributos <strong>de</strong> join,<br />

pero no en los atributos <strong>de</strong> θ . Claramente en ese ejemplo es mala i<strong>de</strong>a<br />

realizar lo antes posible la s<strong>el</strong>ección, puesto que al no existir índices en los<br />

atributos <strong>de</strong> θ aplicar la s<strong>el</strong>ección significaría recorrer todas las tuplas <strong>de</strong> s<br />

(full scan), siendo que es más barato realizar <strong>el</strong> join (por medio <strong>de</strong> los<br />

índices) y luego rechazar las tuplas que no cumplen la s<strong>el</strong>ección.<br />

• Realizar las proyecciones al principio. Esta heurística se ocupa<br />

comúnmente en <strong>el</strong> caso <strong>de</strong> que sea necesario generar una r<strong>el</strong>ación<br />

temporal, se reduce la cantidad <strong>de</strong> atributos a s<strong>el</strong>eccionar, lo que implica<br />

reducir <strong>el</strong> tamaño <strong>de</strong> estas r<strong>el</strong>aciones en gran medida.<br />

Una revisión <strong>de</strong> las reglas <strong>de</strong> equivalencia <strong>de</strong>l apartado 5.4.4.2 pue<strong>de</strong> llevar a la<br />

construcción <strong>de</strong> un algoritmo heurístico que reor<strong>de</strong>ne los componentes <strong>de</strong>l árbol<br />

sintáctico inicial con <strong>el</strong> fin <strong>de</strong> mejorar la ejecución <strong>de</strong> la consulta.<br />

1. Deshacer las s<strong>el</strong>ecciones conjuntivas en una serie <strong>de</strong> s<strong>el</strong>ecciones simples,<br />

basándose en la regla <strong>de</strong> equivalencia número 2 (ver apartado 5.4.4.2).<br />

θ


126<br />

2. Mover las operaciones <strong>de</strong> s<strong>el</strong>ección hacia abajo en <strong>el</strong> árbol <strong>de</strong> la consulta<br />

<strong>para</strong> una ejecución tan pronto como sea posible. Esto se hace posible<br />

aplicando las reglas <strong>de</strong> equivalencia 3, 7.1, 7.2 y 11 (ver apartado 5.4.4.2).<br />

3. Determinar que operaciones <strong>de</strong> s<strong>el</strong>ección y join producirán las r<strong>el</strong>aciones<br />

temporales más pequeñas. Utilizando la asociatividad <strong>de</strong>l join se reforma <strong>el</strong><br />

árbol <strong>de</strong> tal manera que las r<strong>el</strong>aciones <strong>de</strong> los nodos hojas con estas<br />

s<strong>el</strong>ecciones restrictivas se ejecuten primero. Este paso consi<strong>de</strong>ra la<br />

s<strong>el</strong>ectividad <strong>de</strong> una r<strong>el</strong>ación o <strong>de</strong> un join y tiene en cuenta la asociatividad<br />

<strong>de</strong> las operaciones binarias consi<strong>de</strong>radas en las reglas <strong>de</strong> equivalencia 6 y<br />

10 (ver apartado 5.4.4.2).<br />

4. Deshacer y mover tan abajo en <strong>el</strong> árbol como sea posible las listas <strong>de</strong><br />

atributos y proyecciones y crear nuevas proyecciones don<strong>de</strong> sea necesario<br />

(atributos <strong>de</strong> join). Este paso incorpora las reglas <strong>de</strong> equivalencia 3, 8 y 12<br />

(ver apartado 5.4.4.2).<br />

5. I<strong>de</strong>ntificar aqu<strong>el</strong>los subárboles cuyas operaciones se pue<strong>de</strong>n encauzar y<br />

ejecutarlas utilizando encauzamiento (ver apartado 5.4.2).<br />

En resumen : estas heurísticas reor<strong>de</strong>nan la representación inicial <strong>de</strong>l árbol <strong>de</strong> una<br />

consulta <strong>de</strong> tal modo que las operaciones que reducen <strong>el</strong> tamaño <strong>de</strong> los resultados<br />

intermedios se apliquen primero; las s<strong>el</strong>ecciones anticipadas reducen <strong>el</strong> tamaño<br />

<strong>de</strong> tuplas y las proyecciones reducen <strong>el</strong> número <strong>de</strong> atributos. Las transformaciones<br />

heurísticas también reestructuran <strong>el</strong> árbol <strong>para</strong> que las s<strong>el</strong>ecciones y los joins más<br />

restrictivos se realicen antes que otras operaciones similares.


127<br />

La optimización heurística también hace correspon<strong>de</strong>r la expresión <strong>de</strong> la<br />

consulta heurísticamente transformada con secuencias alternativas <strong>de</strong><br />

operaciones <strong>para</strong> producir un conjunto candidato <strong>de</strong> planes evaluación.<br />

Un plan <strong>de</strong> evaluación incluye no sólo las operaciones r<strong>el</strong>acionales a<br />

realizar, sino también los índices a utilizar, <strong>el</strong> or<strong>de</strong>n en que se acce<strong>de</strong>n las tuplas y<br />

<strong>el</strong> or<strong>de</strong>n en que se tienen que producir las operaciones.


128<br />

Capítulo 6. El Optimizador <strong>de</strong> Consultas <strong>de</strong> Sybase<br />

Adaptive Server Enterprise, un ejemplo práctico.<br />

6.1. Introducción.<br />

El optimizador <strong>de</strong> <strong>consultas</strong> <strong>de</strong> Sybase Adaptive Server Enterprise (ASE -<br />

llamado antiguamente SQL-Server) se basa en estimaciones <strong>de</strong> costos, <strong>el</strong> objetivo<br />

principal es, entonces, encontrar <strong>el</strong> camino <strong>de</strong> acceso más barato que minimice <strong>el</strong><br />

tiempo total <strong>de</strong> una consulta. Para alcanzar este objetivo, <strong>el</strong> optimizador <strong>de</strong><br />

<strong>consultas</strong> <strong>de</strong> ASE buscará caminos <strong>de</strong> acceso que:<br />

en:<br />

• Minimicen <strong>el</strong> acceso a páginas lógicas<br />

• Minimicen <strong>el</strong> acceso a páginas físicas.<br />

Los pasos que <strong>el</strong> optimizador ocupa <strong>para</strong> analizar una consulta son :<br />

1. Análisis sintáctico (Parser) <strong>de</strong> la consulta validando a<strong>de</strong>más las referencias<br />

<strong>de</strong> objetos.<br />

2. Optimización <strong>de</strong> la consulta y generación <strong>de</strong>l plan <strong>de</strong> la consulta.<br />

3. Compilación <strong>de</strong>l plan <strong>de</strong> la consulta.<br />

4. Ejecución <strong>de</strong>l plan y <strong>de</strong>volución <strong>de</strong>l resultado al usuario.<br />

Un estudio más <strong>de</strong>tallado sobre <strong>el</strong> paso 2 llevará a una subdivisión <strong>de</strong> este


1. Análisis <strong>de</strong> la consulta.<br />

2. S<strong>el</strong>ección <strong>de</strong> Índices.<br />

3. S<strong>el</strong>ección <strong>de</strong> los or<strong>de</strong>nes <strong>de</strong> Join.<br />

4. Uso <strong>de</strong> tablas temporales (Worktables).<br />

5. S<strong>el</strong>ección <strong>de</strong>l plan.<br />

6.2. Análisis <strong>de</strong> la Consulta.<br />

129<br />

El primer paso que realiza ASE es analizar cada tabla <strong>de</strong> la consulta con <strong>el</strong><br />

fin <strong>de</strong> reconocer los SARG (argumentos <strong>de</strong> búsqueda), las cláusulas OR y las<br />

cláusulas <strong>de</strong> JOIN. La i<strong>de</strong>ntificación <strong>de</strong> estas cláusulas sirve <strong>para</strong> que se utilicen<br />

en la siguiente etapa <strong>para</strong> s<strong>el</strong>eccionar índices.<br />

Cláusulas SARG : La existencia <strong>de</strong> SARG en una consulta habilita al optimizador<br />

a limitar <strong>el</strong> número <strong>de</strong> filas que satisfacen la consulta. El objetivo general es calzar<br />

un SARG con un índice <strong>para</strong> evitar un table scan. Los operadores validos <strong>de</strong> un<br />

SARG son =, >, =, y


130<br />

Se recomienda, siempre que se pueda, reescribir una consulta que tenga<br />

un operador <strong>de</strong> <strong>de</strong>sigualdad a una que contenga SARG. Por ejemplo, si se tiene la<br />

consulta<br />

SELECT NOMBRE FROM DUEÑO WHERE VIGENCIA 0<br />

Se pue<strong>de</strong> rescribir como :<br />

SELECT NOMBRE FROM DUEÑO WHERE VIGENCIA = 1<br />

La cual contiene un SARG valido que <strong>el</strong> optimizador reconocerá y lo<br />

consi<strong>de</strong>rará <strong>para</strong> calzarlo con algún índice.<br />

Algunas sentencias no se ven como SARG, sin embargo, pue<strong>de</strong>n ser<br />

transformadas a SARG por <strong>el</strong> optimizador, estas son :<br />

• BETWEEN se transforma en >= AND = ’01-01-2001’ AND FECHA = AND <<br />

NOMBRE LIKE “Sm%”


se transforma en:<br />

NOMBRE >= “Sm” AND NOMBRE


TABLA1.COLUMNA operador TABLE2.COLUMNA<br />

132<br />

Comúnmente un join involucra 2 tablas al menos que sea un Join recursivo<br />

(aunque en este caso se <strong>de</strong>be especificar la tabla 2 veces).<br />

Existen casos en que una subconsulta se pue<strong>de</strong> expresar como Join. En<br />

general ASE intentará transformar una subconsulta en un Join <strong>para</strong> permitirle al<br />

optimizador s<strong>el</strong>eccionar <strong>el</strong> or<strong>de</strong>n <strong>de</strong> Join más apropiado. Cuando ASE encuentra<br />

una subconsulta <strong>de</strong>l tipo IN, ANY o EXISTS tratará <strong>de</strong> transformarla en un tipo<br />

especial <strong>de</strong> Join <strong>de</strong>nominado Join <strong>de</strong> existencia. Un Join <strong>de</strong> existencia se pue<strong>de</strong><br />

optimizar <strong>de</strong> la misma forma que un Join Normal, excepto que <strong>para</strong> <strong>el</strong> caso <strong>de</strong> los<br />

Join <strong>de</strong> existencia, tan pronto como se cumpla <strong>el</strong> predicado <strong>de</strong> Join <strong>para</strong> la<br />

r<strong>el</strong>ación interna, <strong>el</strong> optimizador <strong>de</strong>tiene la búsqueda <strong>de</strong> valores coinci<strong>de</strong>ntes en la<br />

r<strong>el</strong>ación interna y <strong>de</strong>vu<strong>el</strong>ve un valor TRUE (verda<strong>de</strong>ro).<br />

Si ASE no pue<strong>de</strong> transformar la subconsulta en un Join <strong>de</strong> existencia, la<br />

consulta <strong>de</strong>be ser procesada <strong>de</strong>s<strong>de</strong> a<strong>de</strong>ntro hacia fuera, esto es, se <strong>de</strong>be ejecutar<br />

la subconsulta y luego efectuar <strong>el</strong> Join con la R<strong>el</strong>ación externa, se plantea como<br />

ejemplo la siguiente consulta extraída <strong>de</strong> la Base <strong>de</strong> datos <strong>de</strong> ejemplo PUBS2 <strong>de</strong><br />

ASE:<br />

s<strong>el</strong>ect pub_name<br />

from publishers<br />

where pub_id not in (<br />

s<strong>el</strong>ect pub_id<br />

from titles<br />

where type = 'business')


será procesada por <strong>el</strong> optimizador <strong>de</strong> ASE <strong>de</strong> la siguiente forma :<br />

s<strong>el</strong>ect p.pub_id,<br />

tmp_fi<strong>el</strong>d = t.pub_id<br />

into #worktable<br />

from publishers p,<br />

titles t<br />

where p.pub_id *= t.pub_id and<br />

t.type = 'business'<br />

s<strong>el</strong>ect pub_name<br />

from publishers p,<br />

#worktable w<br />

where p.pub_id = w.pub_id and<br />

tmp_fi<strong>el</strong>d = NULL<br />

drop table #worktable<br />

133<br />

Una subconsulta corr<strong>el</strong>acionada contiene una referencia a una tabla externa<br />

en la cláusula <strong>de</strong> join en la subconsulta, Por ejemplo, la subconsulta siguiente:<br />

s<strong>el</strong>ect col_a<br />

from table_1 t1<br />

where col_b = ( s<strong>el</strong>ect sum(col_x<br />

from table_2<br />

where col_y = t1.col_c)


134<br />

ASE procesará esta subconsulta <strong>de</strong>s<strong>de</strong> a<strong>de</strong>ntro hacia fuera usando una<br />

tabla intermedia al igual que en <strong>el</strong> ejemplo anterior, la consulta anterior quedará<br />

<strong>de</strong>la siguiente manera:<br />

s<strong>el</strong>ect t1.col_c,<br />

suma = sum(t2.col_x)<br />

into #worktable<br />

from table_1 t1,<br />

table_2 t2<br />

where t2.col_c = t1.col_c<br />

s<strong>el</strong>ect t1.col_a<br />

from table1 t1,<br />

#worktable w<br />

where t1.col_c w.col_c and<br />

t1.col_b = w.suma<br />

drop table #worktable<br />

Para <strong>el</strong> procesamiento <strong>de</strong> algunas sub<strong>consultas</strong> ASE usa un una porción<br />

<strong>de</strong>l caché <strong>de</strong> memoria que almacena los resultados <strong>para</strong> cada una <strong>de</strong> las<br />

ejecuciones subsecuentes <strong>de</strong> la subconsulta. Esto ayuda a mejorar <strong>el</strong> rendimiento<br />

cuando hay valores duplicados en las columnas <strong>de</strong> Join.


135<br />

Mientras se procesa la consulta, <strong>el</strong> optimizador evalúa la efectividad <strong>de</strong>l<br />

caché, si este índice se ve bajo, <strong>el</strong> optimizador <strong>de</strong>termina que <strong>el</strong> caché <strong>de</strong><br />

sub<strong>consultas</strong> es inútil y lo reduce en tamaño.<br />

6.3. S<strong>el</strong>ección <strong>de</strong> Índices.<br />

Una vez que la fase <strong>de</strong> análisis <strong>de</strong> la consulta se ha completado <strong>el</strong> próximo<br />

paso es hacer calzar las cláusulas i<strong>de</strong>ntificadas anteriormente con los índices<br />

disponibles en la base <strong>de</strong> datos y estimar los costos <strong>de</strong> entrada y salida. Al igual<br />

que en <strong>el</strong> caso <strong>de</strong> System R, <strong>el</strong> costo <strong>de</strong> cada uno <strong>de</strong> los caminos <strong>de</strong> accesos por<br />

índices se com<strong>para</strong>n entre <strong>el</strong>los y se com<strong>para</strong>n con <strong>el</strong> costo <strong>de</strong> un table scan con<br />

<strong>el</strong> fin <strong>de</strong> <strong>de</strong>terminar <strong>el</strong> menor <strong>de</strong> <strong>el</strong>los.<br />

Al igual que System R, Sybase usa las estadísticas <strong>de</strong> distribución <strong>de</strong> datos<br />

<strong>de</strong>l catálogo <strong>para</strong> estimar <strong>el</strong> costo <strong>de</strong> los caminos <strong>de</strong> acceso, en <strong>el</strong> caso <strong>de</strong> que no<br />

existan estadísticas Sybase también ocupa los “números mágicos”, estos números<br />

son:<br />

Operador Porcentaje estimado <strong>de</strong> filas<br />

= 10%<br />

BETWEEN, > y < 25%<br />

>, =,


136<br />

Si la consulta contiene una cláusula <strong>de</strong> Join ASE buscará los índices que<br />

calcen con los atributos <strong>de</strong> Join, <strong>para</strong> este caso utiliza las estadísticas <strong>de</strong> <strong>de</strong>nsidad<br />

<strong>de</strong> índices las cuales estiman <strong>el</strong> número <strong>de</strong> ocurrencias <strong>de</strong> un valor en un índice.<br />

Si esta estadística no está disponible <strong>el</strong> optimizador estima <strong>el</strong> número <strong>de</strong> filas<br />

coinci<strong>de</strong>ntes con la fórmula:<br />

1 / número <strong>de</strong> filas en la tablas con menos filas<br />

por ejemplo, si tenemos una tabla A <strong>de</strong> 1.000.000 <strong>de</strong> filas y una tabla B con<br />

5.000 filas, la s<strong>el</strong>ectividad <strong>de</strong>l Join será <strong>de</strong> 1 / 5.000 = 0,0002; así <strong>para</strong> cada fila <strong>de</strong><br />

la tabla B se <strong>de</strong>berían esperar 1.000.000 * 0,0002 = 200 filas coinci<strong>de</strong>ntes con la<br />

tabla A.<br />

Ahora bien, en <strong>el</strong> caso <strong>de</strong> haber índices en los atributos <strong>de</strong> Join, ASE<br />

estimará la <strong>de</strong>nsidad <strong>de</strong> un índice como <strong>el</strong> porcentaje <strong>de</strong> valores únicos en un<br />

índice, si se tienen 1.000 valores distintos en <strong>el</strong> índice <strong>de</strong> la tabla A, la <strong>de</strong>nsidad<br />

<strong>de</strong>l índice <strong>de</strong>bería ser : 1 / 1.000 = 0,001; usando este valor <strong>de</strong> <strong>de</strong>nsidad, <strong>para</strong><br />

cada fila <strong>de</strong> la tabla B se esperan 1.000.000 * 0,001 = 1000 filas coinci<strong>de</strong>ntes con<br />

la cláusula <strong>de</strong> join.<br />

A menos que se utilice una cláusula OR, ASE utilizará un solo índice por<br />

tabla <strong>para</strong> satisfacer la consulta, <strong>el</strong> índice <strong>el</strong>egido <strong>de</strong>be ser <strong>el</strong> que requiera <strong>el</strong><br />

menor número <strong>de</strong> E/S <strong>para</strong> resolver la consulta.<br />

Como se ha visto anteriormente, hay instancias don<strong>de</strong> un table scan pue<strong>de</strong><br />

ser la mejor estrategia <strong>para</strong> la recuperación <strong>de</strong> los datos.<br />

Para cualquier caso <strong>el</strong> cálculo <strong>de</strong> la estimación <strong>de</strong> E/S es <strong>el</strong> mismo que se<br />

explicó en la sección 5.3.1, este es, <strong>el</strong> número <strong>de</strong> paginas <strong>de</strong> la tabla <strong>para</strong> <strong>el</strong> caso


137<br />

<strong>de</strong> un table scan, valor que se rescata <strong>de</strong> la página OAM [Rankins96] (object<br />

allocation map) <strong>de</strong> la tabla.<br />

En <strong>el</strong> caso <strong>de</strong> que exista un índice en cluster <strong>el</strong> costo se estimará como <strong>el</strong><br />

número <strong>de</strong> niv<strong>el</strong>es <strong>de</strong>l índice más <strong>el</strong> número <strong>de</strong> páginas a recorrer; este último<br />

valor a su vez se <strong>de</strong>termina como <strong>el</strong> producto entre <strong>el</strong> número estimado <strong>de</strong> filas a<br />

recuperar y <strong>el</strong> número <strong>de</strong> filas por página.<br />

Para un índice que no sea en cluster, <strong>el</strong> costo se estima como:<br />

Número <strong>de</strong> niv<strong>el</strong>es <strong>de</strong>l índice +<br />

El número <strong>de</strong> página <strong>de</strong>l niv<strong>el</strong> <strong>de</strong> hojas +<br />

El número <strong>de</strong> filas estimadas a rescatar (peor caso)<br />

Para índices únicos y <strong>para</strong> equi-join <strong>el</strong> costo <strong>de</strong> E/S e estima como una<br />

página <strong>de</strong> datos más <strong>el</strong> número <strong>de</strong> niv<strong>el</strong>es <strong>de</strong> índices que se <strong>de</strong>ben recorrer <strong>para</strong><br />

acce<strong>de</strong>r a la página <strong>de</strong> datos.<br />

Adicionalmente ASE utiliza la técnica <strong>de</strong> “cubrimiento <strong>de</strong>l índice” (in<strong>de</strong>x<br />

covering) la cual usa <strong>el</strong> niv<strong>el</strong> <strong>de</strong> hojas <strong>de</strong>l índice normal (no en cluster) <strong>de</strong> la<br />

misma manera que lo hace con <strong>el</strong> niv<strong>el</strong> <strong>de</strong> hoja <strong>de</strong> los índices en cluster, siempre y<br />

cuando todos los atributos que se necesitan se encuentren en la <strong>de</strong>finición <strong>de</strong>l<br />

índice. De esta manera <strong>el</strong> optimizador no acce<strong>de</strong> a las páginas <strong>de</strong> datos dado que<br />

tiene todos lo necesario en las páginas <strong>de</strong> índices.<br />

6.4. S<strong>el</strong>ección <strong>de</strong> los or<strong>de</strong>nes <strong>de</strong> Join.


138<br />

El optimizador <strong>de</strong> <strong>consultas</strong> evalúa todos los posibles or<strong>de</strong>nes <strong>de</strong> join y <strong>para</strong><br />

cada or<strong>de</strong>n <strong>de</strong> join consi<strong>de</strong>rado estima <strong>el</strong> costo <strong>de</strong> las diferentes alternativas <strong>de</strong><br />

índices <strong>para</strong> cada una <strong>de</strong> las tablas que participan en <strong>el</strong> Join.<br />

En <strong>el</strong> caso <strong>de</strong> que no hayan índices útiles <strong>para</strong> la consulta en una o más <strong>de</strong><br />

las tablas involucradas en <strong>el</strong> join, ASE consi<strong>de</strong>rará aplicar la estrategia <strong>de</strong><br />

reformateo <strong>para</strong> resolver la consulta eficientemente.<br />

De aquí que, <strong>el</strong> plan <strong>de</strong> consulta más optimo <strong>para</strong> un join involucra <strong>el</strong>egir los<br />

mejores índices <strong>para</strong> cada tabla y <strong>el</strong> or<strong>de</strong>n más eficiente <strong>para</strong> procesar las tablas<br />

en <strong>el</strong> join.<br />

6.4.1. Determinación <strong>de</strong> los or<strong>de</strong>nes <strong>de</strong> Join.<br />

Dado que <strong>el</strong> optimizador <strong>de</strong> ASE se basa en costos, <strong>el</strong> or<strong>de</strong>n <strong>de</strong> las tablas<br />

en la cláusula FROM no dicta <strong>el</strong> or<strong>de</strong>n en <strong>el</strong> cual las tablas <strong>de</strong>ben ser procesadas.<br />

Cuando se procesa un Join, <strong>el</strong> optimizador evalúa todas las permutaciones<br />

razonables y estima <strong>el</strong> costo total <strong>de</strong> E/S en términos <strong>de</strong> tiempo <strong>de</strong> E/S.<br />

El plan que resulta producto <strong>de</strong> la estimación más baja <strong>de</strong> los tiempos <strong>de</strong><br />

E/S será <strong>el</strong> plan <strong>el</strong>egido.<br />

Para minimizar <strong>el</strong> número <strong>de</strong> permutaciones que <strong>de</strong>ben ser examinadas, <strong>el</strong><br />

optimizador <strong>de</strong>sintegra <strong>el</strong> join <strong>de</strong> más <strong>de</strong> 4 tablas en todos los posibles grupos <strong>de</strong><br />

4 con <strong>el</strong> fin <strong>de</strong> evaluar las permutaciones <strong>de</strong> Join <strong>de</strong>ntro <strong>de</strong> cada uno <strong>de</strong> estos<br />

grupos.


139<br />

Esta alternativa es una solución iterativa, que se repite hasta que se<br />

<strong>de</strong>terminen los or<strong>de</strong>nes <strong>de</strong> Join <strong>para</strong> todas las tablas. El propósito <strong>de</strong> este alcance<br />

es limitar <strong>el</strong> número <strong>de</strong> permutaciones que <strong>el</strong> optimizador tenga que consi<strong>de</strong>rar.<br />

El algoritmo usado por ASE <strong>para</strong> procesar los Joins <strong>de</strong> más <strong>de</strong> 4 tablas es<br />

como sigue:<br />

1. Agrupar las tablas en todos los posibles grupos <strong>de</strong> 4.<br />

2. Para cada uno <strong>de</strong> estos grupos estimar <strong>el</strong> costo <strong>de</strong> join <strong>para</strong> cada una <strong>de</strong><br />

las permutaciones (4! = 24).<br />

3. <strong>de</strong>terminar <strong>el</strong> grupo con la permutación <strong>de</strong> menor costo, la primera tabla <strong>de</strong><br />

esta permutación se <strong>de</strong>ja como la tabla más externa <strong>de</strong>l join y se extrae <strong>de</strong><br />

la lista <strong>de</strong> tablas.<br />

4. Repetir los pasos 1, 2, 3 <strong>para</strong> las tablas que quedan, hasta que que<strong>de</strong>n sólo<br />

4 tablas. Estas 4 tablas sirven <strong>de</strong> entrada <strong>para</strong> la ultima estimación <strong>de</strong> costo<br />

<strong>de</strong> Join.<br />

Ejemplo:<br />

Supóngase una consulta que involucre 6 tablas, sean estas tablas T1, T2,<br />

T3, T4, T5, T6; Agrupando estas 6 tablas en todos los posibles grupos <strong>de</strong> 4 se<br />

tendrán :<br />

T1T2T3T4<br />

⎛6<br />

⎞<br />

⎜ ⎟ = 15 grupos<br />

⎝4⎠<br />

T1T2T3T5 T1T2T3T6 T1T2T4T5 T1T2T4T6


T1T2T5T6 T1T3T4T5 T1T3T4T6 T1T3T5T6 T1T4T5T6<br />

T2T3T4T5 T2T3T4T6 T2T3T5T6 T2T4T5T6 T3T4T5T6<br />

140<br />

Para cada grupo <strong>de</strong> 4 encontrar la permutación con costo más bajo y tomar<br />

la primera tabla <strong>de</strong> esa permutación, extraerla <strong>de</strong> la lista <strong>de</strong> tablas y <strong>de</strong>jarla como<br />

la tabla más externa <strong>de</strong>l Join.<br />

Asumiendo que la mejor permutación es: T3T5T4T2, la tabla T3 será la<br />

tablas más externa. Las tablas que quedan son reagrupadas en todos los posibles<br />

grupos <strong>de</strong> 4, la cantidad <strong>de</strong> grupos resultantes es:<br />

⎛5<br />

⎞<br />

⎜ ⎟ = 5 grupos<br />

⎝4⎠<br />

T1T2T4T5 T1T2T4T6 T1T2T5T6 T1T4T5T6 T2T4T5T6<br />

Si la permutación <strong>de</strong> costo más bajo es T4T2T5T6; será entonces la tabla<br />

T4 la segunda tabla más externa en la consulta. De aquí en a<strong>de</strong>lante quedan 4<br />

tablas por lo tanto se encuentra la permutación con menor costo <strong>de</strong> estas,<br />

supóngase que esta permutación es T5T2T1T6, este or<strong>de</strong>n <strong>de</strong> Join se agrega a<br />

las 2 tablas extraídas anteriormente quedando <strong>el</strong> or<strong>de</strong>n <strong>de</strong> Join <strong>de</strong> la consulta<br />

como :<br />

T3 T4 T5 T2 T1 T6<br />

El número <strong>de</strong> permutaciones examinadas con este algoritmo pue<strong>de</strong> ser<br />

sustancialmente menor especialmente cuando <strong>el</strong> número <strong>de</strong> tablas en la consulta<br />

exce<strong>de</strong> las 8 tablas.


141<br />

El beneficio principal <strong>de</strong> este algoritmo es economizar tiempo <strong>de</strong> CPU en la<br />

i<strong>de</strong>ntificación <strong>de</strong>l mejor or<strong>de</strong>n <strong>de</strong> Join. El número resultante <strong>de</strong> combinaciones<br />

⎛ n!<br />

⎞<br />

examinadas con este alcance es la suma <strong>de</strong> ⎜ ⎟ <strong>para</strong> cada iteración.<br />

⎝ ( n − 4)!<br />

⎠<br />

Para este ejemplo <strong>el</strong> número <strong>de</strong> permutaciones consi<strong>de</strong>radas <strong>de</strong>bería ser:<br />

6!<br />

5 4!<br />

+ + = 360 + 120 + 24 = 504<br />

( 6 − 4)!<br />

( 5 − 4)!<br />

( 4 − 4)!<br />

Valor que es mucho menor que las 6! = 720 permutaciones.<br />

Esto representa, <strong>para</strong> este ejemplo, un ahorro <strong>de</strong> un 30%. En la medida que<br />

<strong>el</strong> número <strong>de</strong> tablas se incrementa <strong>el</strong> ahorro se hace cada vez más significativo<br />

como se muestra en la siguiente tabla:<br />

Número<br />

<strong>de</strong> Tablas<br />

N! Método<br />

Optimizado<br />

Ahorro<br />

6 720 504 30%<br />

7 5040 1344 73.3%<br />

8 40320 3024 92.5%<br />

9 362880 6048 98.3%<br />

10 3628800 11088 99.7%<br />

16 20922789888000 148512 99.999%<br />

6.4.2. Estimación <strong>de</strong> los costos.<br />

Para cada permutación estudiada <strong>el</strong> optimizador <strong>de</strong> ASE <strong>de</strong>be estimar <strong>el</strong><br />

costo <strong>de</strong> ese or<strong>de</strong>n <strong>de</strong> Join particular en términos <strong>de</strong> E/S total. Con propósitos <strong>de</strong><br />

com<strong>para</strong>ción, ASE estima <strong>el</strong> total <strong>de</strong> E/S lógicas por tabla y <strong>el</strong> número <strong>de</strong> E/S


142<br />

físicas por tabla, luego las suma y lo transforma en un estimado <strong>de</strong>l tiempo total<br />

transcurrido.<br />

ASE tasa una lectura lógica en 2 ms. (milisegundos) y una lectura física en<br />

18 ms. Por lo tanto la razón entre las lecturas lógicas y las físicas es <strong>de</strong> 1 a 9.<br />

Estos valores son físicos e in<strong>de</strong>pendientes <strong>de</strong> la plataforma en la cual se ejecuta <strong>el</strong><br />

motor.<br />

Ejemplos :<br />

Sea la siguiente consulta <strong>de</strong> la Base <strong>de</strong> Datos PUBS2 <strong>de</strong> ASE:<br />

S<strong>el</strong>ect *<br />

From titles t, titleauthor ta<br />

Where t.title_id = ta.title_id and ta.royaltyper < 50<br />

Se hacen las siguientes suposiciones.<br />

• 15.000 filas en titles (15 filas por página), 1.000 páginas.<br />

• 25.000 filas en titleauthor (50 filas por página), 500 páginas.<br />

• Las estadísticas <strong>de</strong>l Índice en cluster sobre <strong>el</strong> atributo royaltyper <strong>de</strong> la<br />

tabla titleauthor indican que <strong>el</strong> 20% <strong>de</strong> las filas cumplen con<br />

royaltyper < 50.<br />

• Hay suficiente tamaño en <strong>el</strong> caché <strong>para</strong> mantener ambas tablas en<br />

memoria.


Ejemplo 1: tabla titles como tabla externa, estudio sin índices.<br />

143<br />

Para la tabla externa hay un costo <strong>de</strong> 1.000 páginas <strong>para</strong> leer la tabla<br />

completa con un table scan, al usar bucles anidados se necesita leer la tabla<br />

titleautor por cada fila <strong>de</strong> la tabla author, como hay 15.000 filas en la tabla<br />

externa, ASE <strong>de</strong>berá recorrer 15.000 veces las 500 páginas <strong>de</strong> la tabla interna.<br />

El número total <strong>de</strong> E/S <strong>para</strong> esta consulta se estima como:<br />

1.000 + (15.000 * 500) = 7.501.000 E/S.<br />

Luego ASE calcula los costos r<strong>el</strong>ativos <strong>para</strong> cada permutación, <strong>el</strong> primer<br />

scan en la tabla titles realiza 1.000 lecturas lógicas y 1.000 lecturas físicas.<br />

Para la tabla titleauthor, como cabe enteramente en <strong>el</strong> caché sólo se<br />

necesitan 500 lecturas físicas y 15.000 lecturas lógicas <strong>para</strong> cada una <strong>de</strong> las<br />

iteraciones. Por lo tanto:<br />

(1.000 * 18 + 1.000 * 2) + 500 * 18 + 15.000 * 500 * 2 = 15.029.000 ms =<br />

15.029 segundos ≈ 4 horas.<br />

Ejemplo 2: tabla titleauthor como tabla externa, sin índices<br />

500 paginas <strong>de</strong>l table-scan <strong>de</strong> la tabla externa.<br />

Dado que existe un SARG en la tabla titleauthor y asumiendo que no<br />

hay índices y por lo tanto no hay información estadística, ASE asume que un 33%<br />

<strong>de</strong> las filas <strong>de</strong>berían calzar con <strong>el</strong> argumento <strong>de</strong> búsqueda. Así ASE estima que<br />

sólo se <strong>de</strong>berían realizar 8.250 iteraciones en la tabla titles (si una fila <strong>de</strong> la<br />

tabla titleuthor no cumple con <strong>el</strong> SARG no se <strong>de</strong>be efectuar la iteración <strong>para</strong> esa<br />

fila).


Por lo tanto <strong>el</strong> costo r<strong>el</strong>ativo <strong>de</strong> la consulta es:<br />

144<br />

(500 * 18 + 500 * 2) + 1.000 * 18 + 8.250 * 1.000 * 2 = 16.528.000 ms =<br />

16.528 segundos ≈ 4.5 horas.<br />

Ejemplo 3: tabla titleauthor como tabla externa, índice en cluster sobre <strong>el</strong><br />

campo titleauthor.royaltyper, índice único en cluster sobre <strong>el</strong> campo titles.title_id.<br />

Dada la información estadística que indica que sólo <strong>el</strong> 20% <strong>de</strong> las tuplas <strong>de</strong><br />

titleauthor cumplen con <strong>el</strong> SARG, entonces ASE estima que 25.000 * 0,2 =<br />

5.000 filas <strong>de</strong> la tabla titleauthor cumplen con <strong>el</strong> SARG. Como <strong>el</strong> índice en<br />

cluster permite búsquedas por rango, ASE sólo <strong>de</strong>berá recorrer las tuplas que<br />

cumplen con la condición, estas son 5.000 filas / 50 filas por página = 100 páginas.<br />

A<strong>de</strong>más, como hay un índice único en cluster en la tabla titles sólo una<br />

fila <strong>de</strong>be calzar con cada fila iterada <strong>de</strong> la tabla titleauthor, osea 5.000 filas. A<br />

15 filas por página se tienen 5.000 / 15 = 334 páginas <strong>de</strong> datos a acce<strong>de</strong>r en<br />

titles mientras se procesa la consulta. Cada búsqueda simple todavía cuesta 3<br />

accesos a disco más. Con esta información ASE estima que la consulta <strong>de</strong>bería<br />

costar:<br />

100 páginas en titleauthor + (5.000 filas en titleauthor * 3 páginas<br />

por búsqueda en titles) = 15.500<br />

100 lecturas físicas en titleauthor: 18 * 100 = 1.800 ms.<br />

100 lecturas lógicas en titleauthor: 2 * 100 = 200 ms.<br />

334 lecturas físicas en titles: 18 * 334 = 6.012 ms.<br />

15000 lecturas lógicas en titles: 2 * 15.000 = 30.000 ms.


Total = 38.012 ms. ≈ 38 segundos.<br />

6.4.3. Estrategia <strong>de</strong> Reformateo.<br />

145<br />

Como se vio en los ejemplos anteriores, <strong>el</strong> escenario <strong>de</strong> costo en <strong>el</strong> peor<br />

caso <strong>para</strong> un join es <strong>el</strong> que implementa un table-scan en ambas tablas, la fórmula<br />

<strong>de</strong> costo resultante es:<br />

número <strong>de</strong> paginas <strong>de</strong> la tabla externa +<br />

(número <strong>de</strong> filas <strong>de</strong> la tabla externa *<br />

número <strong>de</strong> paginas <strong>de</strong> la tabla interna)<br />

Ocasionalmente pue<strong>de</strong> resultar más barato construir un índice temporal en<br />

cluster en la tabla interna y utilizarlo <strong>para</strong> procesar la consulta que recorre<br />

repetidas veces la tabla. Cuando esto ocurre, ASE es copia <strong>el</strong> contenido <strong>de</strong> la<br />

tabla en una tabla temporal en la base <strong>de</strong> datos tempdb y crea un índice en<br />

cluster en la(s) columnas <strong>de</strong> join, luego utiliza este índice <strong>para</strong> recorrer la tabla y<br />

así sólo recuperar las filas que califican <strong>para</strong> con la condición <strong>de</strong> Join.<br />

El costo <strong>de</strong> aplicar la estrategia <strong>de</strong> reformateo es <strong>el</strong> costo <strong>de</strong> las E/S<br />

requeridas <strong>para</strong> crear la tabla temporal más <strong>el</strong> costo <strong>de</strong> crear <strong>el</strong> índice en <strong>el</strong>la.<br />

Sybase calcula esta fórmula como sigue:<br />

P2 + log2 P2 * P2; don<strong>de</strong> P2 es <strong>el</strong> número <strong>de</strong> páginas <strong>de</strong> la tabla interna.<br />

Esta estrategia no se usará a menos que <strong>el</strong> costo estimado sea menor que<br />

<strong>el</strong> costo <strong>de</strong> hacer un join con table scan en la tabla interna. El costo total <strong>de</strong><br />

procesar la consulta <strong>de</strong>bería ser <strong>el</strong> costo <strong>de</strong> reformateo más <strong>el</strong> número <strong>de</strong> páginas<br />

<strong>de</strong> la tabla externa (P1) más <strong>el</strong> número <strong>de</strong> filas <strong>de</strong> la tabla externa (R1)


146<br />

multiplicado por <strong>el</strong> número <strong>de</strong> scans en la tabla externa. La ecuación completa que<br />

estima <strong>el</strong> costo <strong>de</strong> E/S <strong>para</strong> una consulta utilizando la estrategia <strong>de</strong> reformateo<br />

sería:<br />

(P2 + log2 P2 * P2) + P1 + R1<br />

Como ejemplo, supóngase que se tiene una tabla externa <strong>de</strong> 300 filas y 200<br />

páginas y una tabla interna que consiste en 100 páginas, <strong>el</strong> costo <strong>de</strong> reformateo<br />

será entonces :<br />

(100 + log2 100 * 100) + 200 + 300 ≈ 1300 E/S.<br />

Mientras que <strong>el</strong> costo <strong>de</strong> procesar la consulta usando table scan sería<br />

200 + (300 * 100) = 30.200 E/S.<br />

El uso <strong>de</strong> la estrategia <strong>de</strong> reformateo por parte <strong>de</strong>l optimizador <strong>de</strong> ASE,<br />

indica al usuario que seguramente no tiene <strong>de</strong>finidos los índices apropiados <strong>para</strong><br />

las tablas. Es válido pensar que la estrategia <strong>de</strong> reformateo es más efectiva que<br />

un table scan, sin embargo, no es menos cierto que una buena <strong>de</strong>finición <strong>de</strong><br />

índices es mucho más apropiada y <strong>de</strong> mejor resultado.<br />

6.4.4. Outer Joins.<br />

La sintaxis <strong>de</strong> un outer join en ASE se <strong>de</strong>fine con un asterisco (*) en <strong>el</strong> lado<br />

<strong>de</strong> la cláusula <strong>de</strong> join don<strong>de</strong> se <strong>de</strong>sea que se incluyan todas las filas.


147<br />

Tal y como se ha explicado en la sección 5.3.3.7 un outer join indicara que<br />

todas las filas <strong>de</strong> la tabla <strong>de</strong>l lado <strong>de</strong>l * tienen que ser incluidas en <strong>el</strong> resultado sin<br />

importar si la fila calce o no con la cláusula <strong>de</strong> join.<br />

En estos casos la tabla <strong>de</strong>l lado <strong>de</strong>l asterisco será forzada a ser tratada<br />

como la tabla externa (outer) y por lo tanto <strong>para</strong> este tipo <strong>de</strong> join, ASE no evaluará<br />

un join <strong>de</strong> or<strong>de</strong>n inverso.<br />

6.5. Uso <strong>de</strong> tablas temporales.<br />

Cuando <strong>el</strong> optimizador encuentra cláusulas ORDER BY, GROUP BY y<br />

DISTINCT comúnmente <strong>de</strong>terminará la creación <strong>de</strong> tablas temporales<br />

(worktables). Dado que las tablas temporales producen un procesamiento<br />

adicional y consumo <strong>de</strong> E/S <strong>el</strong> optimizador <strong>de</strong>be <strong>de</strong>cidir si <strong>de</strong>be crear o no estas<br />

tablas.<br />

Para <strong>el</strong> caso <strong>de</strong> la cláusula GROUP BY, siempre se <strong>de</strong>be crear una tabla<br />

temporal <strong>para</strong> realizar <strong>el</strong> agrupamiento y guardar cualquier valor agregado que se<br />

está generando <strong>para</strong> cada uno <strong>de</strong> los grupos solicitados.<br />

Para <strong>el</strong> caso <strong>de</strong> la cláusula DISTINCT, y como esta cláusula se aplica a<br />

todos los atributos <strong>de</strong> una fila, se <strong>de</strong>be crear una tabla que or<strong>de</strong>ne los valores y<br />

<strong>el</strong>imine los duplicados. Si existe un índice único en la tabla y todos los atributos <strong>de</strong><br />

este índice se han incluidos en <strong>el</strong> SELECT, se evitará la creación <strong>de</strong> la tabla<br />

temporal dado que <strong>el</strong> índice único garantiza la que cada fila es distinta.<br />

Para <strong>el</strong> caso <strong>de</strong> la cláusula ORDER BY, la utilización <strong>de</strong> una tabla<br />

<strong>de</strong>pen<strong>de</strong>rá <strong>de</strong> los índices sobre la tabla.


148<br />

Considérese la situación en la cual existe un índice en cluster sobre una<br />

tabla, la cláusula ORDER BY especifica como mínimo la primera columna <strong>de</strong>l<br />

índice en cluster y no especifica columnas que no sean parte <strong>de</strong>l índice. En este<br />

caso no se requiere crear una tabla temporal dado que la consulta se pue<strong>de</strong><br />

resolver ya sea por la exploración <strong>de</strong>l índice en cluster o por medio <strong>de</strong> un table<br />

scan. Sin embargo, si existe un índice que no sea en cluster y que a<strong>de</strong>más fue<br />

utilizado <strong>para</strong> resolver la consulta, se requiere una tabla temporal que or<strong>de</strong>ne los<br />

datos extraídos por medio <strong>de</strong>l índice no en cluster.<br />

No se necesitará la creación <strong>de</strong> una tabla temporal si la cláusula ORDER<br />

BY especifica al menos la primera columna <strong>de</strong> un índice normal (no en cluster)<br />

don<strong>de</strong> no hay columnas que no sean parte <strong>de</strong>l índice, y a<strong>de</strong>más sea este <strong>el</strong> índice<br />

que se utiliza <strong>para</strong> satisfacer un SARG.<br />

Ejemplo: s<strong>el</strong>ect * from table where text like “texto%”<br />

or<strong>de</strong>r by text<br />

6.6. S<strong>el</strong>ección <strong>de</strong>l plan.<br />

La s<strong>el</strong>ección <strong>de</strong>l plan <strong>de</strong> ejecución <strong>de</strong> una consulta estará entonces<br />

<strong>de</strong>terminada por la solución que tenga <strong>el</strong> menor costo estimado <strong>para</strong> la consulta<br />

referenciada, dado que esta <strong>el</strong>ección se estima, hay veces en que <strong>el</strong> usuario<br />

pue<strong>de</strong> estar un tanto escéptico acerca <strong>de</strong> si es <strong>el</strong> plan <strong>el</strong>egido <strong>el</strong> más optimo <strong>para</strong><br />

la consulta. Se hace necesaria entonces, información técnica específica acerca <strong>de</strong>l<br />

plan <strong>de</strong> ejecución que ayu<strong>de</strong> al usuario a respon<strong>de</strong>r las siguiente preguntas.<br />

• ¿ Consi<strong>de</strong>ró <strong>el</strong> optimizador los índices que se <strong>de</strong>finieron <strong>para</strong> cada una<br />

<strong>de</strong> las tablas o está realizando un table scan ? ( punto 6.3)


• ¿ Se utilizan tablas temporales <strong>para</strong> procesar la consulta ? (punto 6.5)<br />

• ¿ Se aplicó la estrategia <strong>de</strong> reformateo si es <strong>el</strong> caso ? (punto 6.4.3)<br />

149<br />

• ¿ Cuales son los ór<strong>de</strong>nes <strong>de</strong> Join que utiliza <strong>el</strong> optimizador <strong>para</strong> resolver<br />

la consulta ? (punto 6.4)<br />

• ¿ Como son las estimaciones <strong>de</strong> costo con respecto a los costos<br />

originales?<br />

Con <strong>el</strong> fin <strong>de</strong> conocer las respuestas a estas preguntas ASE proporciona<br />

una herramienta llamada set showplan on que <strong>de</strong>vu<strong>el</strong>ve al cliente un <strong>de</strong>talle<br />

<strong>de</strong>l plan <strong>de</strong> ejecución <strong>el</strong>egido <strong>para</strong> resolver la consulta. El análisis <strong>de</strong> la<br />

información que entrega esta opción escapa al alcance <strong>de</strong> este trabajo, <strong>para</strong> un<br />

estudio más <strong>de</strong>tallado <strong>de</strong>l tema se recomienda leer [Rankins96].<br />

6.6.1. Potenciales problemas <strong>de</strong>l optimizador y sus soluciones.<br />

Luego <strong>de</strong> escribir la consulta y leer <strong>el</strong> plan <strong>de</strong> ejecución, es posible que <strong>el</strong><br />

usuario <strong>de</strong>termine que <strong>el</strong> optimizador no esté <strong>el</strong>igiendo <strong>el</strong> plan más óptimo. A<br />

continuación se <strong>de</strong>tallan los problemas más comunes que llevan al optimizador a<br />

<strong>el</strong>egir un plan <strong>de</strong> ejecución pobre en términos <strong>de</strong> eficacia.<br />

Estadísticas actualizadas. Uno <strong>de</strong> los problemas más comunes<br />

encontrados en ambientes <strong>de</strong> producción es que, ya sea, las estadísticas no están<br />

disponibles <strong>para</strong> los índices, o bien, están <strong>de</strong>sactualizadas. Se recomienda<br />

entonces actualizar las estadísticas y re-ejecutar la consulta.


150<br />

Cláusulas SARG. Revisar la existencia <strong>de</strong> cláusulas SARG <strong>de</strong>ntro <strong>de</strong>l<br />

WHERE. Fijar atención en operadores <strong>de</strong> <strong>de</strong>sigualdad, operaciones sobre<br />

columnas y expresiones constantes que no puedan ser evaluadas en <strong>el</strong> momento<br />

<strong>de</strong> la compilación <strong>de</strong> la consulta.<br />

Índices que cubren <strong>consultas</strong>. Si lo que se espera es una cobertura <strong>de</strong><br />

índice, chequear que todos los campos <strong>de</strong>l índice estén presentes en la consulta.<br />

La falta <strong>de</strong> uno <strong>de</strong> <strong>el</strong>los lleva a una recuperación <strong>de</strong> datos que involucra toda la<br />

fila.<br />

Estrategia <strong>de</strong> reformateo. Si se está efectuando una estrategia <strong>de</strong><br />

reformateo, significa que, ya sea no existen índices <strong>para</strong> la consulta, o la consulta<br />

contiene SARGSs no optimizados que no pue<strong>de</strong>n utilizar los índices disponibles.<br />

Se recomienda reevaluar la in<strong>de</strong>xación <strong>de</strong> tablas o rescribir la consulta <strong>de</strong> manera<br />

que utilice los índices disponibles.<br />

6.6.2. Mejoras propias <strong>de</strong>l optimizador <strong>de</strong> ASE.<br />

En cada versión que se lanza al mercado, los motores <strong>de</strong> base <strong>de</strong> datos<br />

tradicionales tien<strong>de</strong>n a mejorar las características <strong>de</strong> optimización <strong>de</strong> <strong>consultas</strong>, en<br />

<strong>el</strong> caso <strong>de</strong> ASE, estas mejorías tienen que ver con <strong>el</strong> manejo <strong>de</strong> memoria y con las<br />

estadísticas <strong>de</strong>l catálogo.<br />

Ya en la versión 11, una <strong>de</strong> las mejoras está en la habilidad <strong>de</strong> po<strong>de</strong>r<br />

particionar <strong>el</strong> caché <strong>de</strong> datos y asignar objetos a diferentes particiones <strong>de</strong>l caché.<br />

Otra mejora está en <strong>el</strong> hecho <strong>de</strong> realizar E/S <strong>de</strong> hasta 16 Kb. <strong>de</strong> tamaño (<strong>el</strong><br />

tamaño <strong>de</strong> un extent) y no en bloques <strong>de</strong> 2 Kb. (<strong>el</strong> tamaño <strong>de</strong> la página <strong>de</strong> datos<br />

<strong>de</strong> Sybase).


151<br />

Una lectura <strong>de</strong> datos en bloques <strong>de</strong> 16 Kb. pue<strong>de</strong> ayudar a mejorar <strong>el</strong><br />

rendimiento <strong>de</strong> las <strong>consultas</strong> que rescatan un alto número <strong>de</strong> paginas<br />

secuenciales <strong>de</strong> datos minimizando así <strong>el</strong> número <strong>de</strong> accesos a disco. Las<br />

<strong>consultas</strong> que se pue<strong>de</strong>n beneficiar con este tipo <strong>de</strong> estrategia son las <strong>consultas</strong><br />

<strong>de</strong>l tipo:<br />

• Table scan.<br />

• Consultas por rango que utilizan índices en cluster.<br />

• Consultas cubiertas por índices simples (no en cluster)<br />

Por lo tanto, si <strong>el</strong> caché que utiliza <strong>para</strong> leer la tabla o índice está<br />

configurado <strong>para</strong> lecturas largas, <strong>el</strong> optimizador tomará ventaja <strong>de</strong> esto e intentará<br />

realizar lecturas <strong>de</strong> este tipo.<br />

Otra característica <strong>de</strong> esta versión es la habilidad que tiene <strong>el</strong> optimizador<br />

<strong>de</strong> usar la llamada estrategia <strong>de</strong> fetch-and-discard <strong>para</strong> las páginas que se leen <strong>de</strong><br />

disco. Un caché <strong>de</strong> ASE se compone <strong>de</strong> dos ca<strong>de</strong>nas, <strong>el</strong> MRU(Most Recently<br />

Used - más recientemente usado) y LRU (Least Recently Used - menos<br />

recientemente usado), en versiones anteriores a la versión 11 <strong>de</strong> ASE la estrategia<br />

<strong>de</strong>l uso <strong>de</strong>l caché era <strong>de</strong>l tipo FIFO (first in- first out), lo que significaba que toda<br />

página cargada en <strong>el</strong> caché <strong>de</strong>bía recorrerlo completamente efectuando <strong>el</strong> mismo<br />

número <strong>de</strong> saltos antes <strong>de</strong> ser reemplazada. Esto muchas veces dañaba <strong>el</strong><br />

rendimiento, sobre todo cuando se <strong>de</strong>bía leer una tabla gran<strong>de</strong> y las paginas (que<br />

seguramente sólo se iban a utilizar una sola vez) quedaban en <strong>el</strong> caché,<br />

colocando a las paginas que si necesitaban estar frecuentemente en <strong>el</strong> caché al<br />

final <strong>de</strong>l LRU.<br />

La estrategia <strong>de</strong> fetch-and-discard le permite al optimizador <strong>de</strong>terminar si<br />

una consulta es <strong>de</strong>l tipo <strong>de</strong> <strong>consultas</strong> que lee los datos una sola vez y no los


152<br />

necesita nuevamente. Si la consulta es <strong>de</strong> este tipo, <strong>el</strong> optimizador colocará la<br />

página al final <strong>de</strong>l LRU, <strong>de</strong> manera que no “empuje” fuera <strong>de</strong>l caché a las paginas<br />

que <strong>de</strong>berían permanecer en él. La versión 12 <strong>de</strong> ASE a<strong>de</strong>más le permite al<br />

usuario <strong>de</strong>terminar que estrategia <strong>de</strong> reemplazo utilizar <strong>para</strong> cada una <strong>de</strong> las<br />

tablas que se consi<strong>de</strong>ran en un join.<br />

Las <strong>consultas</strong> con las cuales <strong>el</strong> optimizador <strong>de</strong> ASE le aplica la estrategia<br />

<strong>de</strong> fetch-and-discard son las <strong>consultas</strong> <strong>de</strong>l tipo:<br />

• Table scan<br />

• Consultas por rango que utilizan índices en cluster.<br />

• Consultas cubiertas por índices simples (no en cluster)<br />

• La tabla externa en un Join (sólo se requiere un scan <strong>para</strong> recorrerla)<br />

• La tabla interna <strong>de</strong> un join, si esta no cabe completamente en <strong>el</strong> cache.<br />

6.7. Resumen.<br />

A lo largo <strong>de</strong> los años, <strong>el</strong> optimizador <strong>de</strong> ASE ha sufrido continuas mejoras<br />

(al igual que la mayoría <strong>de</strong> los optimizadores <strong>para</strong> motores comerciales), en esta<br />

sección se ha verificado la correspon<strong>de</strong>ncia entre la teoría expuesta a lo largo <strong>de</strong>l<br />

capítulo Capítulo 5 y la implementación comercial <strong>de</strong> uno <strong>de</strong> los motores <strong>de</strong> base<br />

<strong>de</strong> datos más conocidos en la actualidad.<br />

Se <strong>de</strong>muestra a<strong>de</strong>más que en la mayoría <strong>de</strong> las oportunida<strong>de</strong>s <strong>el</strong><br />

optimizador toma la <strong>de</strong>cisión correcta, sin embargo, hay ocasiones en las que <strong>el</strong><br />

optimizador pue<strong>de</strong> tomar una mala <strong>de</strong>cisión <strong>de</strong>bido a una imprecisa o incompleta<br />

información en las estadísticas <strong>de</strong>l catálogo como también en algunas<br />

consi<strong>de</strong>raciones <strong>de</strong> cómo se escribe la consulta.


153<br />

Ahora bien, cuando existen sospechas acerca <strong>de</strong> la <strong>el</strong>ección <strong>de</strong>l plan, ASE<br />

(como los <strong>de</strong>más motores <strong>de</strong> base <strong>de</strong> datos comerciales) disponen <strong>de</strong><br />

herramientas que proporcionan información acerca <strong>de</strong> las <strong>de</strong>cisiones tomadas<br />

<strong>para</strong> la <strong>el</strong>ección <strong>de</strong>l plan más óptimo.


Resumen y Conclusiones.<br />

Resumen<br />

154<br />

El procesamiento <strong>de</strong> <strong>consultas</strong> tiene varias etapas a seguir <strong>para</strong> resolver<br />

una consulta SQL, las características <strong>de</strong>l mo<strong>de</strong>lo r<strong>el</strong>acional permiten que cada<br />

motor <strong>de</strong> base <strong>de</strong> datos <strong>el</strong>ija su propia representación que, comúnmente, resulta<br />

ser <strong>el</strong> álgebra r<strong>el</strong>acional. La optimización <strong>de</strong> <strong>consultas</strong> es, entonces, una <strong>de</strong> estas<br />

etapas (que por cierto otros mo<strong>de</strong>los <strong>de</strong> bases <strong>de</strong> datos no poseen).<br />

Existen distintos métodos <strong>para</strong> optimizar <strong>consultas</strong> r<strong>el</strong>acionales, sin<br />

embargo <strong>el</strong> enfoque <strong>de</strong> optimización basada en costos combinado con heurísticas<br />

que permitan reducir <strong>el</strong> espacio <strong>de</strong> búsqueda <strong>de</strong> la solución es <strong>el</strong> método<br />

mayormente utilizado por los motores <strong>de</strong> base <strong>de</strong> datos r<strong>el</strong>aciones <strong>de</strong> la<br />

actualidad, en todo caso, in<strong>de</strong>pendiente <strong>de</strong>l método <strong>el</strong>egido <strong>para</strong> optimizar la<br />

consulta, la salida <strong>de</strong> este proceso <strong>de</strong>be ser un plan <strong>de</strong> ejecución, <strong>el</strong> cual<br />

comúnmente es representado en su forma <strong>de</strong> árbol r<strong>el</strong>acional.<br />

La optimización <strong>de</strong> <strong>consultas</strong> en base a costos supone la utilización <strong>de</strong> una<br />

medida <strong>de</strong> costo que sea común a lo largo <strong>de</strong>l proceso, esta medida <strong>de</strong>be<br />

representar <strong>el</strong> criterio <strong>de</strong> minimización en la utilización <strong>de</strong> recursos <strong>de</strong>l sistema, la<br />

medida estándar <strong>para</strong> bases <strong>de</strong> datos r<strong>el</strong>acionales es usualmente la cantidad <strong>de</strong><br />

E/S (tanto <strong>de</strong> disco como <strong>de</strong> la memoria intermedia). Este enfoque estima un costo<br />

que estará <strong>de</strong>terminado por formulas pre<strong>de</strong>finidas y por la información <strong>de</strong>l catalogo<br />

inherente a la consulta. Sin embargo <strong>el</strong> optimizador no siempre escoge <strong>el</strong> plan<br />

más optimo, ya que una búsqueda exhaustiva <strong>de</strong> la estrategia óptima pue<strong>de</strong><br />

consumir <strong>de</strong>masiado tiempo <strong>de</strong> proceso. Se dice entonces que <strong>el</strong> optimizador<br />

escoge una estrategia “razonablemente eficiente”.


155<br />

El catálogo <strong>de</strong> la base <strong>de</strong> datos guarda información estadística <strong>de</strong> cada una<br />

<strong>de</strong> las r<strong>el</strong>aciones como también <strong>de</strong> los índices <strong>de</strong> cada una <strong>de</strong> la r<strong>el</strong>aciones, estas<br />

estadísticas permiten estimar los tamaños <strong>de</strong> los resultados <strong>de</strong> varias<br />

operaciones. Esta información es particularmente útil cuando se dispone <strong>de</strong><br />

índices <strong>para</strong> auxiliar <strong>el</strong> procesamiento <strong>de</strong> la consulta, sin embargo, la existencia <strong>de</strong><br />

estas estructuras influencia <strong>de</strong> manera significativa en la <strong>el</strong>ección <strong>de</strong>l plan <strong>de</strong><br />

ejecución <strong>de</strong> la consulta.<br />

Una mala administración <strong>de</strong> la información que contiene <strong>el</strong> catálogo<br />

conducirá inevitablemente a una <strong>de</strong>safortunada <strong>el</strong>ección <strong>de</strong>l plan <strong>de</strong> ejecución.<br />

Para ayudar a solucionar este problema existen varios enfoques que conjunta o<br />

se<strong>para</strong>damente pue<strong>de</strong>n asistir al optimizador en su <strong>el</strong>ección. Uno <strong>de</strong> estos<br />

consiste en la actualización automática <strong>de</strong> las estadísticas que algunos motores<br />

<strong>de</strong> base <strong>de</strong> datos incluyen como opción. Otro enfoque es la opción <strong>de</strong> guardar en<br />

<strong>el</strong> catálogo planes <strong>de</strong> ejecución precalculados que a<strong>de</strong>más le ahorran al motor <strong>el</strong><br />

tiempo <strong>de</strong> cálculo <strong>de</strong>l plan. Obviamente estos planes son vulnerables a ser<br />

invalidados si se producen cambios lógicos en <strong>el</strong> esquema <strong>de</strong> la base <strong>de</strong> datos o<br />

si hay un cambio en la distribución <strong>de</strong> los datos a ser recuperados.<br />

Uno <strong>de</strong> los primeros optimizadores <strong>de</strong> <strong>consultas</strong> y <strong>el</strong> que se conoce como<br />

base <strong>para</strong> la mayoría <strong>de</strong> los optimizadores tradicionales es <strong>el</strong> optimizador <strong>de</strong><br />

System R. System R es un optimizador basado en costos pero que utiliza<br />

heurísticas <strong>para</strong> <strong>de</strong>splazar s<strong>el</strong>ecciones y proyecciones hacia abajo en <strong>el</strong> árbol <strong>de</strong><br />

la consulta, la resolución <strong>de</strong> joins se realiza mediante <strong>el</strong> uso <strong>de</strong> árboles <strong>de</strong><br />

profundidad por la izquierda O(n!) lo que permite <strong>el</strong> uso <strong>de</strong> evaluaciones<br />

encauzadas cuando sea posible. La estimación <strong>de</strong> los caminos <strong>de</strong> acceso <strong>para</strong><br />

índices secundarios supone que se necesita un acceso a disco por cada tupla <strong>de</strong><br />

la r<strong>el</strong>ación lo que supone <strong>el</strong> peor caso. Es probable que la estimación sea precisa


156<br />

con tamaños <strong>de</strong> buffer pequeños, sin embargo con un buffer <strong>de</strong> mayor tamaño la<br />

página que contiene la tupla podria estar todavía en memoria.<br />

Las contribuciones <strong>de</strong>l optimizador <strong>de</strong> system R con respecto a otras<br />

investigaciones hechas hasta ese entonces se basan en un mejor<br />

aprovechamiento <strong>de</strong> las estadísticas <strong>de</strong>l catálogo, la inclusión <strong>de</strong> la utilización <strong>de</strong><br />

CPU en las fórmulas <strong>de</strong>l cálculo <strong>de</strong> costos y los métodos <strong>para</strong> <strong>de</strong>terminar or<strong>de</strong>nes<br />

<strong>de</strong> join. El concepto <strong>de</strong> “factor <strong>de</strong> s<strong>el</strong>ección” le permite al optimizador estimar<br />

cuantas tuplas satisfacen los predicados <strong>de</strong> antemano, <strong>el</strong> concepto <strong>de</strong> “interesting<br />

or<strong>de</strong>rs” agrega una importancia r<strong>el</strong>ativa al or<strong>de</strong>n en que se solicito la salida, por lo<br />

tanto agrega un niv<strong>el</strong> <strong>de</strong> importancia a todos aqu<strong>el</strong>los or<strong>de</strong>namientos que<br />

respondan al or<strong>de</strong>n solicitado permitiendo evitar (cuando sea posible) un<br />

reor<strong>de</strong>namiento <strong>de</strong>l resultado final.<br />

En General, la teoría expuesta en <strong>el</strong> capítulo Capítulo 5 valida las<br />

investigaciones hechas a partir <strong>de</strong> system R, planteando <strong>el</strong> proceso <strong>de</strong><br />

optimización <strong>de</strong> <strong>consultas</strong> como sigue.<br />

El primer paso <strong>de</strong> un optimizador <strong>de</strong> <strong>consultas</strong> es encontrar una expresión<br />

<strong>de</strong>l álgebra <strong>de</strong> r<strong>el</strong>aciones que sea equivalente a la expresión dada y cuyo costo<br />

estimado <strong>de</strong> ejecución sea menor. En <strong>el</strong> apartado 5.4.4.2 se presenta una lista <strong>de</strong><br />

equivalencia <strong>de</strong> expresiones que se pue<strong>de</strong>n utilizar <strong>para</strong> transformar una<br />

expresión en otra equivalente, se usan estas reglas <strong>para</strong> generar<br />

sistemáticamente todas las expresiones equivalentes <strong>de</strong> la consulta y luego <strong>el</strong>egir<br />

la más barata. Dado que generalmente esta evaluación se basa en costos, se<br />

presentan en <strong>el</strong> apartado 5.3.1, 5.3.2 y 5.3.3 distintos algoritmos <strong>para</strong> la s<strong>el</strong>ección<br />

<strong>de</strong> caminos <strong>de</strong> acceso a r<strong>el</strong>aciones simples, a joins y <strong>consultas</strong> complejas, estas<br />

medidas están <strong>de</strong>terminadas por la información que se tiene en <strong>el</strong> catálogo <strong>de</strong> la<br />

base <strong>de</strong> datos.


157<br />

Para <strong>el</strong> caso <strong>de</strong> <strong>consultas</strong> a r<strong>el</strong>aciones simples se utilizará entonces la<br />

evaluación <strong>de</strong> cada una <strong>de</strong> las expresiones equivalentes con su evaluación <strong>de</strong><br />

costos <strong>para</strong> <strong>el</strong>egir <strong>el</strong> plan <strong>de</strong> acceso a la consulta más barato.<br />

Para <strong>el</strong> caso <strong>de</strong> Joins es necesario incluir <strong>el</strong> cálculo <strong>de</strong> or<strong>de</strong>nes <strong>de</strong> join, que<br />

consi<strong>de</strong>rará or<strong>de</strong>namientos y encauzamientos en la medida <strong>de</strong> los posible. Dado<br />

que <strong>el</strong> cálculo <strong>de</strong> estos or<strong>de</strong>namientos pue<strong>de</strong> ser costoso mientras más r<strong>el</strong>aciones<br />

estén involucradas en un Join, se presenta en <strong>el</strong> apartado 5.5 distintas técnicas<br />

<strong>para</strong> <strong>el</strong> cálculo <strong>de</strong> estos or<strong>de</strong>namientos, estas técnicas comúnmente iterativas<br />

introducen distintas heurísticas <strong>para</strong> reducir <strong>el</strong> espacio <strong>de</strong> búsqueda <strong>de</strong> soluciones<br />

buscando mejorarlo en cada iteración.<br />

Bajo este alero <strong>de</strong> teoría, se presenta en <strong>el</strong> capítulo Capítulo 6 un ejemplo<br />

práctico <strong>de</strong> cómo un motor <strong>de</strong> base <strong>de</strong> datos r<strong>el</strong>acional comercial enfrenta estos<br />

problema en la actualidad.<br />

Conclusiones.<br />

El <strong>lenguaje</strong> <strong>de</strong> <strong>consultas</strong> SQL tiene la gran particularidad <strong>de</strong> que (a menos<br />

que se exprese directamente) le <strong>de</strong>ja la tarea la <strong>el</strong>ección <strong>de</strong> caminos <strong>de</strong> accesos y<br />

técnicas <strong>de</strong> recuperación <strong>de</strong> datos al motor <strong>de</strong> procesamiento <strong>de</strong> <strong>consultas</strong>. Al<br />

in<strong>de</strong>pendizar <strong>de</strong> esta tarea al usuario final, se hacen necesarios un conjunto <strong>de</strong><br />

técnicas que permitan asegurar al motor que los datos serán rescatados <strong>de</strong> la<br />

manera “más optima posible”. Este componente es <strong>el</strong> optimizador <strong>de</strong> <strong>consultas</strong>, <strong>el</strong><br />

cual se encarga <strong>de</strong> <strong>el</strong>egir <strong>el</strong> plan <strong>de</strong> evaluación más apropiado dada la información<br />

con la que cuenta <strong>de</strong> <strong>el</strong> catalogo y una serie <strong>de</strong> técnicas y algoritmos pre<strong>de</strong>finidos<br />

<strong>para</strong> estos efectos.


158<br />

Por muy importante que sea <strong>el</strong> la etapa <strong>de</strong> optimización en una consulta (y<br />

<strong>de</strong> hecho lo es), existen casos en que la búsqueda <strong>de</strong>l plan más optimo <strong>de</strong><br />

ejecución <strong>de</strong> una consulta pue<strong>de</strong> tomar mucho tiempo, <strong>para</strong> solucionar este<br />

problema, los optimizadores se apoyan en heurísticas, en técnicas <strong>de</strong> búsquedas<br />

aleatorias y en reglas pre<strong>de</strong>finidas, con <strong>el</strong> fin <strong>de</strong> que, no abarcando todo <strong>el</strong> espacio<br />

<strong>de</strong> búsqueda, se dé con una solución que sea “razonablemente aceptable”<br />

Existen distintos enfoques <strong>para</strong> optimizar una consulta, sin embargo, y a<br />

partir <strong>de</strong> conclusiones hechas por las investigaciones <strong>de</strong> system R, la mayoría <strong>de</strong><br />

los optimizadores han <strong>el</strong>egido <strong>el</strong> enfoque <strong>de</strong> optimización basada en costos como<br />

pre<strong>de</strong>terminada. La utilización <strong>de</strong> <strong>el</strong> enfoque <strong>de</strong> optimización basada en costos se<br />

fundamenta en la necesidad <strong>de</strong> contar con una medida que sea representativa <strong>de</strong>l<br />

criterio <strong>de</strong> minimización en la utilización <strong>de</strong> recursos <strong>de</strong>l sistema. Esta medida<br />

pue<strong>de</strong> no ser la misma, <strong>de</strong>pendiendo <strong>de</strong>l tipo <strong>de</strong> SGBD y <strong>de</strong> los avances<br />

tecnológicos que se han logrado con <strong>el</strong> pasar <strong>de</strong>l tiempo, por ejemplo, system R<br />

utilizaba como medida <strong>de</strong> costo una medida <strong>de</strong> peso entre costos <strong>de</strong> E/S y<br />

utilización <strong>de</strong>l uso <strong>de</strong> CPU, actualmente, existe una ten<strong>de</strong>ncia (cuestionable a mi<br />

parecer) a obviar <strong>el</strong> uso <strong>de</strong> CPU como medida representativa <strong>de</strong> costos, dado los<br />

avances tecnológicos en este campo.<br />

Una <strong>de</strong> las ventajas que se logra comprendiendo <strong>el</strong> proceso <strong>de</strong> optimización<br />

<strong>de</strong> <strong>consultas</strong> es la <strong>de</strong> enten<strong>de</strong>r que es lo que hace realmente un optimizador y con<br />

esto evitar la construcción <strong>de</strong> malas <strong>consultas</strong>.<br />

Sin Embargo, nada <strong>de</strong> esto cobra mucha importancia si <strong>el</strong> diseño <strong>de</strong> la base<br />

<strong>de</strong> datos es pobre, estudios indican que <strong>el</strong> 65% <strong>de</strong> los problemas <strong>de</strong> tunning en<br />

bases <strong>de</strong> datos en ambientes <strong>de</strong> producción es <strong>de</strong>bido a un pobre diseño <strong>de</strong> la<br />

base <strong>de</strong> datos. En estos casos, por mucho capacidad e hardware que se le<br />

agregue al sistema no se logrará un mayor índice <strong>de</strong> rendimiento en la base <strong>de</strong><br />

datos.


son:<br />

159<br />

Algunas consi<strong>de</strong>raciones que ayudan al buen diseño <strong>de</strong> una base <strong>de</strong> datos<br />

• Seguir los estándares <strong>de</strong> normalización <strong>de</strong> base <strong>de</strong> datos.<br />

• Tratar <strong>de</strong> maximizar <strong>el</strong> uso <strong>de</strong> índices en cluster<br />

• Tratar <strong>de</strong> reducir <strong>el</strong> número <strong>de</strong> índices secundarios (no en cluster)<br />

• Si existen <strong>consultas</strong> que involucren más <strong>de</strong> 4 tablas en un Join se<br />

recomienda <strong>de</strong>snormalizar algunas tablas.<br />

• Para tablas potencialmente gran<strong>de</strong>s se recomienda <strong>el</strong> particionamiento<br />

horizontal <strong>de</strong> tablas (varias tablas con la misma estructura original pero con<br />

datos distribuidos por cierto criterio pre<strong>de</strong>finido).


Bibliografía.<br />

[Bj<strong>el</strong>etich99]<br />

[Comer79]<br />

[Codd71]<br />

[Date98]<br />

[Ioannidis96]<br />

[Kline99]<br />

[Kruse84]<br />

[Lorie78]<br />

160<br />

S. Bj<strong>el</strong>etich, G. Mable, “Microsoft SQL Server 7 Al <strong>de</strong>scubierto”, Prentice<br />

Hall, Madrid 1999, Traducción <strong>de</strong> “Microsoft SQL Server 7.0 Unleashed”<br />

,SAMS 1999.<br />

D. Comer, "The Ubiquitous B-tree", ACM Computer Surveys, Volumen<br />

11, Número 2, Junio 1979, pp. 121-137.<br />

E. F. Codd, “R<strong>el</strong>ational completeness of data base sublanguages”. In<br />

Courant Computer Science Symposium on Data Base Systems, volumen<br />

6, paginas 65 -- 98. Prentice-Hall, Mayo 1971.<br />

C. Date, “Fifty Ways to Quote Your Query”, Miller Freeman Inc, USA<br />

1998.<br />

URL http://www.dbpd.com/vault/9807xtra.htm<br />

Y. Ioannidis, "Query Optimization", ACM Computing Surveys,<br />

symposium issue on the 50th Anniversary of ACM, Volumen 28, Número<br />

1, Marzo 1996, pp. 121-123.<br />

K. Kline, L. Gould, A. Zanevsky, “Transact-SQL Programming”, O’Reilly,<br />

USA 1999.<br />

R. L. Kruse, “Estructura <strong>de</strong> datos y diseño <strong>de</strong> programas”, Prentice Hall,<br />

Mexico 1988, traducción <strong>de</strong> “Data Structures and Program Design”,<br />

Prentice-Hall, 1984.<br />

R.A. Lorie, and J.F. Nilsson, “An Access Specification Language for a<br />

R<strong>el</strong>ational Data Base System”. IBM Research Report RJ2218, Abril,<br />

1978.


[McJones97]<br />

[Rankins96]<br />

[S<strong>el</strong>inger79]<br />

[Silberschatz97]<br />

[Steinbrunn93]<br />

[Swami88]<br />

[Sybase01]<br />

[Wong76]<br />

Paul McJones, SRC Technical Note 1997 – 018 “The 1995 SQL<br />

Reunión: People, Projects, and Politics”, Agosto 1997.<br />

R. Rankins, J. R. Garbus, D. Salomon, B. W. McEwan, “Sybase<br />

SQLServer 11 UNLEASHED”, SAMS 1996.<br />

161<br />

P. G. S<strong>el</strong>inger, , M. M. Astrahan, R. Chamberlain, R. A. Lorie, T. Price,<br />

"Access Path S<strong>el</strong>ection in a R<strong>el</strong>ational Database Management System”.<br />

Proce<strong>de</strong>nte <strong>de</strong> la conferencia “ACM SIGMOD Conference”, Junio, 1979.<br />

A. Silberschatz, H. F. Korth, S. Sudarshan, “Fundamentos <strong>de</strong> Bases <strong>de</strong><br />

datos – Tercera Edición”, McGraw – Hill, España 1998, Traducción <strong>de</strong><br />

“Database System Concepts”, McGraw – Hill, USA 1997.<br />

M. Steinbrunn and G. Moerkotte and A. Kemper,"Optimizing Join<br />

Or<strong>de</strong>rs", Passau, Alemania, "1993",<br />

URL<br />

http://citeseer.nj.nec.com/steinbrunn93optimizing.html<br />

A. Swami y A.Gupta. Optimization of large join queries. conferencia ACM<br />

SIGMOD <strong>de</strong> administración <strong>de</strong> datos, USA, 1988<br />

Sybase, “Performance and Tunning gui<strong>de</strong>: Volume 2 – Optimizing and<br />

Abstract Plans”, Sybase, USA 2001.<br />

E. Wong, K. Youssefi, Decomposition – “A Strategy for Query<br />

Processing. ACM Transactions on Database Systems”, 1,3 (Septiembre)<br />

1976.


Apéndices.<br />

A. Sintaxis <strong>de</strong> SQL<br />

A.1. Definiciones <strong>de</strong> datos en SQL<br />

162<br />

Las Sentencias <strong>de</strong>l <strong>lenguaje</strong> <strong>de</strong> <strong>de</strong>finición <strong>de</strong> datos (DDL) que posee SQL<br />

operan en base a tablas. Las Principales sentencias DDL son las siguientes:<br />

• CREATE TABLE<br />

• DROP TABLE<br />

• ALTER TABLE<br />

• CREATE INDEX<br />

• DROP INDEX<br />

Las sentencias antes mencionadas restringen la atención a los aspectos<br />

que son <strong>de</strong> directo interés <strong>para</strong> <strong>el</strong> usuario y no los aspectos que tienen que ver<br />

con <strong>el</strong> niv<strong>el</strong> interno <strong>de</strong>l sistema (tales <strong>de</strong>talles son <strong>de</strong> importancia <strong>para</strong> <strong>el</strong> DBA 15 ).<br />

Una tabla base se <strong>de</strong>fine en los sistemas r<strong>el</strong>acionales como una fila <strong>de</strong><br />

encabezados <strong>de</strong> columnas más cero o más filas con valores <strong>de</strong> datos. Esta tabla<br />

es creada usando la sentencia CREATE TABLE <strong>de</strong>l DDL <strong>de</strong> SQL. La fila <strong>de</strong><br />

encabezados <strong>de</strong> columna especifica una o más columnas asociadas cada una a<br />

sus respectivos tipos <strong>de</strong> datos. Cada fila <strong>de</strong> datos contiene exactamente un valor<br />

<strong>de</strong> dato <strong>para</strong> cada columna.<br />

15 DataBase Administrator . Administrador <strong>de</strong> la base <strong>de</strong> datos.


163<br />

No existe un or<strong>de</strong>n <strong>de</strong> filas, pero es posible imponer un or<strong>de</strong>n sobre <strong>el</strong>las.<br />

Las columnas están or<strong>de</strong>nadas <strong>de</strong> izquierda a <strong>de</strong>recha pero este or<strong>de</strong>n no es<br />

parte <strong>de</strong>l mo<strong>de</strong>lo r<strong>el</strong>acional. Las Tablas son autónomas e in<strong>de</strong>pendientes a<br />

diferencia <strong>de</strong> las vistas las cuales no existen en su propio espacio pero si se<br />

<strong>de</strong>rivan <strong>de</strong> una o más tablas.<br />

A.1.1. Comando CREATE TABLE<br />

El comando CREATE TABLE se usa <strong>para</strong> especificar una nueva r<strong>el</strong>ación<br />

por medio <strong>de</strong> un nombre y especificando cada uno <strong>de</strong> sus atributos. A cada<br />

atributo se le da un nombre, un tipo <strong>de</strong> datos (<strong>para</strong> especificar su dominio) y<br />

algunas constraints 16 sobre <strong>el</strong> atributo.<br />

La sintaxis <strong>de</strong>l comando es :<br />

CREATE TABLE nombre_<strong>de</strong>_tabla<br />

(<strong>de</strong>finicion_<strong>de</strong>_columna [,<strong>de</strong>finicion_<strong>de</strong>_columna ] ...)<br />

don<strong>de</strong> la <strong>de</strong>finición <strong>de</strong> columna es <strong>de</strong> la forma :<br />

nombre_<strong>de</strong>_columna tipo_<strong>de</strong>_dato [ NOT NULL ]<br />

Ejemplo :<br />

create table DUENOS<br />

(<br />

RUT INTEGER not null,<br />

NOMBRE CHAR(30) not null,<br />

TELEFONO CHAR(10) ,<br />

DIRECCION CHAR(50)<br />

);<br />

16 Una Constraint es una regla que se <strong>de</strong>be aplicar a un atributo <strong>de</strong> una tabla. Las<br />

constraints proveen un mecanismo rápido y eficiente <strong>para</strong> asegurar la integridad <strong>de</strong> la base <strong>de</strong><br />

datos sin importar los cambios que requiera <strong>el</strong> usuario.


A.1.1.1. Definición <strong>de</strong> NOT NULL (no nulo)<br />

164<br />

Puesto que SQL permite valores nulos como valores <strong>de</strong> atributos, una<br />

constraint NOT NULL pue<strong>de</strong> ser especificada en un atributo <strong>para</strong> indicar que no se<br />

permiten valores nulos <strong>para</strong> este atributo. En general NOT NULL <strong>de</strong>be ser<br />

especificado <strong>para</strong> los atributos que componen la llave primaria <strong>de</strong> cada r<strong>el</strong>ación.<br />

A.1.1.2. Tipos <strong>de</strong> datos SQL<br />

Los siguientes tipos <strong>de</strong> datos son los comúnmente soportados por <strong>el</strong><br />

estándar SQL.<br />

Datos Numéricos INTEGER Entero con signo <strong>de</strong> 31 bits<br />

SMALLINT Entero con signo <strong>de</strong> 15 bits<br />

DECIMAL(p,q) Número con signo <strong>de</strong> p dígitos, q <strong>de</strong>cimales<br />

FLOAT(p) Número <strong>de</strong> punto flotante, p bits <strong>de</strong> precisión<br />

Datos String CHAR(n) Ca<strong>de</strong>na <strong>de</strong> texto <strong>de</strong> largo fijo <strong>de</strong> n bytes<br />

VARCHAR(n) Ca<strong>de</strong>na <strong>de</strong> texto <strong>de</strong> largo variante, hasta los n bytes<br />

GRAPHIC(n) Ca<strong>de</strong>na <strong>de</strong> texto <strong>de</strong> largo fijo, n*2 bytes<br />

VARGRAPHIC(n<br />

)<br />

Datos <strong>de</strong> Fecha y Hora DATE Fecha (aaaammmdd)<br />

A.1.2. Comando DROP TABLE<br />

TIME Hora (hhmmss)<br />

Ca<strong>de</strong>na <strong>de</strong> texto <strong>de</strong> largo variante, hasta los n*2 bytes<br />

TIMESTAMP Combinación <strong>de</strong> fecha y hora<br />

Tabla A-1 - Tipos <strong>de</strong> datos <strong>de</strong> SQL<br />

El comando DROP TABLE se usa <strong>para</strong> <strong>el</strong>iminar una r<strong>el</strong>ación y su <strong>de</strong>finición<br />

<strong>de</strong> atributos como también borra <strong>de</strong>l catálogo la tupla r<strong>el</strong>acionada a esta.<br />

La sintaxis <strong>de</strong> la Instrucción es :


DROP TABLE nombre_<strong>de</strong>_tabla;<br />

Ejemplo :<br />

drop table DUENOS;<br />

A.1.3. Comando ALTER TABLE<br />

165<br />

El comando ALTER TABLE es usado <strong>para</strong> agregar un atributo a una <strong>de</strong> las<br />

tablas <strong>de</strong> la base <strong>de</strong> datos. A<strong>de</strong>más cambia las tuplas en <strong>el</strong> catalogo <strong>de</strong> sistema<br />

<strong>de</strong> la BD. El nuevo atributo tendrá <strong>el</strong> valor nulo (NULL) en todas la tuplas <strong>de</strong> la<br />

r<strong>el</strong>ación inmediatamente <strong>de</strong>spués <strong>de</strong> ejecutada la instrucción, puesto que no se<br />

permite la constraint NOT NULL. La sintaxis <strong>de</strong> este comando es :<br />

ALTER TABLE nombre_<strong>de</strong>_tabla<br />

ADD nombre_<strong>de</strong>_columna tipo_<strong>de</strong>_dato;<br />

Ejemplo:<br />

alter table DUENOS add VIGENCIA CHAR(1);<br />

A.1.4. Comando CREATE INDEX<br />

El Comando CREATE INDEX se usa <strong>para</strong> crear un índice. Cada índice<br />

tiene un nombre <strong>el</strong> cual será usado <strong>para</strong> borrarlo en caso <strong>de</strong> que no se necesite<br />

más. La sintaxis <strong>de</strong> este comando es la siguiente:<br />

CREATE [ UNIQUE ] INDEX nombre_<strong>de</strong>_indice<br />

ON nombre_<strong>de</strong>_tabla ( nombre_<strong>de</strong>_columna [or<strong>de</strong>n]<br />

[,nombre_<strong>de</strong>_columna [or<strong>de</strong>n] ] ... )<br />

[CLUSTER];


166<br />

CLUSTER: La especificación opcional CLUSTER 17 en un comando CREATE INDEX indica<br />

si este índice estará <strong>el</strong> cluster. Una tabla dada pue<strong>de</strong> tener un sólo índice<br />

en cluster en un momento dado.<br />

ORDER: Toda especificación ORDER en una sentencia SQL CREATE INDEX <strong>de</strong>be ser<br />

ya sea ASC (ascen<strong>de</strong>nte) o DESC (<strong>de</strong>scen<strong>de</strong>nte) y por lo tanto especifica <strong>el</strong><br />

or<strong>de</strong>n en que se organizarán los datos, <strong>el</strong> valor por <strong>de</strong>fecto <strong>para</strong> ORDER es<br />

ASC.<br />

UNIQUE: La opción UNIQUE en una sentencia SQL CREATE INDEX especifica que no<br />

se permitirán dos registros en la tabla a in<strong>de</strong>xar que tengan <strong>el</strong> mismo valor<br />

<strong>para</strong> <strong>el</strong> campo (o la combinación <strong>de</strong> estos) <strong>para</strong> <strong>el</strong> cual se está creando <strong>el</strong><br />

índice.<br />

Ejemplo:<br />

create unique in<strong>de</strong>x DUENO_PK on DUENOS (RUT asc);<br />

A.1.5. Comando DROP INDEX<br />

El comando SQL DROP INDEX se usa <strong>para</strong> soltar <strong>el</strong> índice <strong>de</strong> la tabla<br />

r<strong>el</strong>acionada y borrar la tupla correspondiente <strong>de</strong>s<strong>de</strong> <strong>el</strong> catalogo <strong>de</strong> sistema <strong>de</strong> la<br />

base <strong>de</strong> datos. Una razón <strong>para</strong> borrar índices es que es costoso mantenerlos cada<br />

vez que la r<strong>el</strong>ación base es actualizada y por lo tanto se requiere espacio<br />

adicional. Los índices que especifican una constraint <strong>de</strong> llave (primaria, alterna o<br />

externa) no se pue<strong>de</strong>n borrar a menos que se quiera borrar también la constraint<br />

asociada. La sintaxis <strong>de</strong> la cláusula DROP INDEX es:<br />

DROP INDEX nombre_<strong>de</strong>_indice;<br />

Ejemplo:<br />

drop in<strong>de</strong>x DUENO_PK;<br />

17 La técnica <strong>de</strong> clustering involucra <strong>el</strong> tratar <strong>de</strong> almacenar en disco lo más cerca posible<br />

los registros que están r<strong>el</strong>acionados lógicamente, <strong>de</strong> manera <strong>de</strong> po<strong>de</strong>r mejorar <strong>el</strong> rendimiento.


A.2. Manipulación <strong>de</strong> datos en SQL<br />

SQL provee cuatro sentencias <strong>de</strong> manipulación <strong>de</strong> datos (DML). Esas son:<br />

• SELECT<br />

• UPDATE<br />

• DELETE<br />

• INSERT<br />

A.2.1. Comando SELECT<br />

167<br />

El comando DML SELECT es la sentencia SQL básica <strong>para</strong> la recuperación<br />

<strong>de</strong> información <strong>de</strong>s<strong>de</strong> una base <strong>de</strong> datos. (nótese que <strong>el</strong> comando SELECT <strong>de</strong><br />

SQL no guarda r<strong>el</strong>ación con <strong>el</strong> operador <strong>de</strong> s<strong>el</strong>ección <strong>de</strong>l álgebra r<strong>el</strong>acional). La<br />

sintaxis <strong>de</strong>l comando es la siguiente:<br />

SELECT [DISTINCT] ítem(s)<br />

FROM tabla(s)<br />

[ WHERE condición ]<br />

[ GROUP BY campo(s) ]<br />

[ HAVING condición ]<br />

[ ORDER BY campos]<br />

[ UNION SQL_SELECT]


168<br />

La palabra clave DISTINCT se usa <strong>para</strong> indicar que los valores duplicados o<br />

redundantes <strong>de</strong>ben ser <strong>el</strong>iminados antes que la función sea ejecutada. DISTINCT<br />

pue<strong>de</strong> ser especificada con las funciones agregadas COUNT y AVG pero es<br />

totalmente irr<strong>el</strong>evante <strong>para</strong> las funciones MAX y MIN. No se pue<strong>de</strong> usar esta<br />

cláusula junto con la función especial COUNT(*). La palabra Clave UNIQUE es un<br />

sinónimo <strong>para</strong> DISTINCT y las dos se pue<strong>de</strong>n usar sin distinción.<br />

Ejemplo:<br />

s<strong>el</strong>ect COUNT(DISCTINCT MARCA)<br />

FROM MOVIL;<br />

Retorna <strong>el</strong> número <strong>de</strong> Marcas <strong>de</strong> autos que tiene la empresa<br />

A.2.1.1. Funciones Agregadas <strong>de</strong> la cláusula SELECT<br />

SQL provee algunas funciones especiales que pue<strong>de</strong>n ser usadas con <strong>el</strong><br />

comando SELECT. Esas funciones son las siguientes:<br />

• COUNT<br />

• SUM<br />

• AVG<br />

• MAX<br />

• MIN<br />

• COUNT(*)<br />

COUNT : La función COUNT se usa <strong>para</strong> obtener <strong>el</strong> número <strong>de</strong> valores en la columna. Opera<br />

sobre una colección <strong>de</strong> valores en una columna <strong>de</strong> la tabla. La palabra clave


169<br />

DISTINCT se pue<strong>de</strong> usar conjuntamente con COUNT. Si <strong>el</strong> resultado <strong>de</strong>l argumento es<br />

<strong>el</strong> conjunto vacío la función COUNT retorna <strong>el</strong> valor cero. Un ejemplo <strong>de</strong> COUNT es:<br />

SELECT COUNT (DISTINCT MARCA)<br />

FROM MOVIL;<br />

SUM : La función SUM se usa <strong>para</strong> sumar los valores <strong>de</strong> una columna. La función opera sobre<br />

una colección <strong>de</strong> valores en una columna <strong>de</strong> la tabla. Los valores <strong>de</strong>ben ser numéricos.<br />

Si <strong>el</strong> resultado <strong>de</strong>l argumento es <strong>el</strong> conjunto vacío, SUM retorna NULL. Un ejemplo <strong>de</strong><br />

SUM es:<br />

SELECT SUM (HORA_HASTA - HORA_DESDE)<br />

FROM VIAJE<br />

WHERE PATENTE_MOVIL = 'HL-8483';<br />

AVG : La Función AVG se usa <strong>para</strong> promediar todos los valores s<strong>el</strong>eccionados en una columna,<br />

opera sobre una colección <strong>de</strong> valores (numéricos) en una sola columna <strong>de</strong> la tabla. La<br />

función AVG pue<strong>de</strong> ir precedida por la palabra clave DISTINCT lo cual promediará sólo<br />

los valores únicos. Si <strong>el</strong> resultado <strong>de</strong>l argumento es <strong>el</strong> conjunto vacío, AVG retorna NULL.<br />

Ejemplo :<br />

SELECT AVG (HORA_HASTA - HORA_DESDE)<br />

FROM VIAJE<br />

WHERE PATENTE_MOVIL = 'HL-8483';<br />

MIN (MAX): La función MIN (MAX) se usa <strong>para</strong> obtener <strong>el</strong> menor (mayor) valor en una<br />

columna. Ambas funciones operan sobre una colección <strong>de</strong> valores en una<br />

columna. Los valores no necesitan ser numéricos. Si <strong>el</strong> resultado <strong>de</strong>l argumento<br />

es <strong>el</strong> conjunto vacío, ambas retornan NULL.<br />

Ejemplo:<br />

SELECT MAX (HORA_HASTA - HORA_DESDE)


FROM VIAJE;<br />

SELECT MIN (HORA_HASTA - HORA_DESDE)<br />

FROM VIAJE;<br />

170<br />

COUNT(*): La función COUNT(*) se usa <strong>para</strong> contar la cardinalidad <strong>de</strong> una tabla sin<br />

<strong>el</strong>iminación <strong>de</strong> valores duplicados. En las funciones anteriores, cualquier valor<br />

nulo en <strong>el</strong> argumento se <strong>el</strong>imina antes que la función se aplique<br />

(indiferentemente <strong>de</strong> si se usa o no la cláusula DISTINCT) . COUNT(*) retorna<br />

cero si <strong>el</strong> resultado <strong>de</strong>l argumento es <strong>el</strong> conjunto vacío.<br />

Ejemplo:<br />

SELECT COUNT(*)<br />

FROM VIAJES<br />

WHERE PATENTE_MOVIL = 'HL-8483';<br />

A.2.1.2. Cláusula GROUP BY<br />

La cláusula GROUP BY en una sentencia SELECT reor<strong>de</strong>na lógicamente la<br />

tabla representada por la cláusula FROM en grupos, tal que <strong>de</strong>ntro <strong>de</strong> cada grupo<br />

todas las filas tienen <strong>el</strong> mismo valor <strong>para</strong> <strong>el</strong> campo dado en la cláusula GROUP<br />

BY (esto es conceptual; la tablas no se reor<strong>de</strong>na físicamente en la base <strong>de</strong> datos).<br />

Cada expresión en la cláusula SELECT <strong>de</strong>be ser reducible a valor simple <strong>de</strong>ntro<br />

<strong>de</strong> un grupo, es <strong>de</strong>cir, que pue<strong>de</strong> ser ya sea <strong>el</strong> mismo campo evaluado en la<br />

Cláusula GROUP BY (o talvez una expresión que lo contenga), un literal, o una<br />

función tal como SUM que opera sobre todos los valores <strong>de</strong> un grupo <strong>de</strong>ntro <strong>de</strong> un<br />

campo y que reduce todos aqu<strong>el</strong>los valores a un valor simple.


171<br />

GROUP BY no implica ORDER BY; <strong>para</strong> garantizar que <strong>el</strong> resultado<br />

aparezca en un <strong>de</strong>terminado or<strong>de</strong>n se <strong>de</strong>be especificar también la cláusula<br />

ORDER BY.<br />

Ejemplo:<br />

SELECT PATENTE_MOVIL, SUM(HORA_HASTA - HORA_DESDE)<br />

FROM VIAJE<br />

GROUP BY PATENTE_MOVIL;<br />

A.2.1.3. Cláusula HAVING<br />

La cláusula HAVING en una sentencia SELECT se usa <strong>para</strong> <strong>el</strong>iminar<br />

grupos, (tal como se usa WHERE <strong>para</strong> <strong>el</strong>iminar filas). Si se especifica, <strong>de</strong>be existir<br />

una cláusula GROUP BY también. La Expresión en la cláusula HAVING <strong>de</strong>be ser<br />

reducible a valor simple <strong>de</strong>ntro <strong>de</strong> un grupo.<br />

Ejemplo :<br />

SELECT PATENTE_MOVIL, SUM(HORA_HASTA - HORA_DESDE)<br />

FROM VIAJE<br />

GROUP BY PATENTE_MOVIL<br />

HAVING SUM(HORA_HASTA - HORA_DESDE) > 10;<br />

A.2.1.4. Cláusula ORDER BY<br />

Esta cláusula se utiliza en un comando SELECT <strong>para</strong> producir como<br />

resultado una r<strong>el</strong>ación en un or<strong>de</strong>n específico. En general, la r<strong>el</strong>ación resultado no


172<br />

se garantiza que esté en un or<strong>de</strong>n particular. De ahí que la cláusula ORDER BY<br />

se utilice <strong>para</strong> or<strong>de</strong>nar <strong>el</strong> resultado en alguna secuencia particular antes <strong>de</strong> que los<br />

datos sean <strong>de</strong>splegados.<br />

AL igual que la cláusula ORDER <strong>de</strong>l comando CREATE INDEX <strong>el</strong><br />

argumento pue<strong>de</strong> ser ya sea ASC o DESC. ASC es <strong>el</strong> valor por <strong>de</strong>fecto.<br />

También es posible i<strong>de</strong>ntificar columnas por su número <strong>de</strong> columna en lugar<br />

<strong>de</strong> su nombre, esto es, por la posición ordinal (<strong>de</strong> izquierda a <strong>de</strong>recha) <strong>de</strong> la<br />

columna en cuestión <strong>de</strong>ntro <strong>de</strong> la tabla resultado. Esta característica hace posible<br />

or<strong>de</strong>nar un resultado en base a una columna que no tiene nombre.<br />

Ejemplo:<br />

SELECT RUT, NOMBRE<br />

FROM CHOFER<br />

WHERE SYSDATE < FECHA_LCENCIA_HASTA<br />

ORDER BY 2 DESC;<br />

A.2.1.5. Cláusula EXIST<br />

La cláusula EXISTS en un comando SELECT representa <strong>el</strong> calificador <strong>de</strong><br />

existencia. La expresión se avaluara como verda<strong>de</strong>ra, si y sólo si, <strong>el</strong> resultado <strong>de</strong><br />

evaluar la sentencia “SELECT … FROM …” no es vacía, esto es, si y sólo si,<br />

existe un registro en la tabla dada en FROM <strong>de</strong>s<strong>de</strong> <strong>el</strong> niv<strong>el</strong> más externo <strong>de</strong> la<br />

consulta. La negación (NOT EXISTS) es especialmente importante <strong>para</strong> una cierta<br />

clase <strong>de</strong> <strong>consultas</strong> bastante más complejas que <strong>el</strong> común.<br />

Ejemplo :


SELECT PATENTE<br />

FROM MOVIL<br />

WHERE EXISTS (<br />

A.2.1.6. Sub<strong>consultas</strong>.<br />

SELECT *<br />

FROM VIAJE<br />

WHERE MOVIL.PATENTE =<br />

VIAJE.PATENTE_MOVIL);<br />

173<br />

Una Subconsulta en una cláusula SELECT es una expresión <strong>de</strong> la forma<br />

“SELECT - FROM - WHERE - GROUP BY - HAVING” que se anida <strong>de</strong>ntro <strong>de</strong> otra<br />

expresión. Las Sub<strong>consultas</strong> se usan comúnmente <strong>para</strong> representar un conjunto<br />

<strong>de</strong> valores que se buscan por medio <strong>de</strong> una condición “IN condición”. El sistema<br />

evalúa toda la consulta evaluando la Sub<strong>consultas</strong> anidadas.<br />

Ejemplos :<br />

* Retorna todos los móviles que tienen más <strong>de</strong> 10 horas <strong>de</strong> viaje.<br />

SELECT CHOFER.NOMBRE, MOVIL.PATENTE<br />

FROM MOVIL, CHOFER<br />

WHERE PATENTE IN (<br />

SELECT PATENTE_MOVIL<br />

FROM VIAJE<br />

WHERE (HORA_HASTA - HORA_DESDE) > 10)<br />

AND<br />

MOVIL.RUT_CHOFER = CHOFER.RUT;


A.2.2. Comando UPDATE<br />

174<br />

El comando DML UPDATE se usa <strong>para</strong> modificar valores <strong>de</strong> atributos <strong>de</strong><br />

una o más tuplas s<strong>el</strong>eccionadas. Al igual que con <strong>el</strong> comando SELECT la cláusula<br />

WHERE es la que s<strong>el</strong>ecciona la o las tuplas que serán modificadas <strong>de</strong>s<strong>de</strong> una<br />

r<strong>el</strong>ación simple. La cláusula adicional SET especifica los atributos que serán<br />

modificados y sus nuevos valores.<br />

La Sintaxis <strong>de</strong> UPDATE es la siguiente<br />

UPDATE nombre_<strong>de</strong>_tabla<br />

SET campo = expresion_escalar<br />

[, campo = expresion_escalar ] ...<br />

[ WHERE condicion ] ;<br />

Todos los registros en la tabla que satisfagan la condición serán<br />

modificados <strong>de</strong> acuerdo a sus asignaciones (“campo = expresion_escalar”) en la<br />

cláusula SET.<br />

El siguiente ejemplo <strong>de</strong>muestra <strong>el</strong> uso <strong>de</strong>l comando UPDATE en un<br />

Registro.<br />

UPDATE CHOFER<br />

SET DIRECCION = ‘Otra Dirección’,<br />

TELEFONO = 5555555<br />

WHERE RUT = 12657378<br />

El siguiente ejemplo <strong>de</strong>muestra <strong>el</strong> uso <strong>de</strong>l comando UPDATE <strong>para</strong> un<br />

conjunto <strong>de</strong> registros.


UPDATE CHOFER<br />

A.2.3. Comando DELETE<br />

SET VIGENCIA = ‘N’<br />

WHERE SYSDATE > FECHA_LICENCIA_HASTA;<br />

175<br />

El comando DML DELETE borra tuplas <strong>de</strong>s<strong>de</strong> una r<strong>el</strong>ación. Al igual que <strong>el</strong><br />

comando UPDATE pue<strong>de</strong> incluir la cláusula WHERE <strong>para</strong> s<strong>el</strong>eccionar las tuplas a<br />

ser <strong>el</strong>iminadas. Las tuplas son borradas sólo <strong>de</strong>s<strong>de</strong> una tabla a la vez.<br />

Dependiendo <strong>de</strong>l número <strong>de</strong> tuplas s<strong>el</strong>eccionadas por la condición en la cláusula<br />

WHERE será la cantidad (cero, una o más) <strong>de</strong> tuplas que serán <strong>el</strong>iminadas con un<br />

sólo comando DELETE. Si se omite la cláusula WHERE se asume que todas las<br />

tuplas <strong>de</strong> la r<strong>el</strong>ación <strong>de</strong>ben ser borradas, sin embargo la tabla permanece en la<br />

base <strong>de</strong> datos como una tabla vacía. (<strong>el</strong> comando DROP TABLE se usa <strong>para</strong><br />

<strong>el</strong>iminar completamente la tabla, aún si esta no está vacía).<br />

La sintaxis <strong>de</strong>l comando DELETE es la siguiente :<br />

DELETE<br />

FROM table<br />

[ WHERE condition ] ;<br />

El siguiente ejemplo borra una sola tupla en la tabla base:<br />

DELETE<br />

FROM MOVIL<br />

WHERE PATENTE = 'HL-8205' ;


El siguiente ejemplo borra todas las tuplas que satisfagan la condición<br />

DELETE<br />

A.2.4. Comando INSERT<br />

FROM MOVIL<br />

WHERE ANO


El siguiente es un ejemplo <strong>de</strong> la inserción <strong>de</strong> un sólo registro.<br />

INSERT<br />

INTO DUENO ( RUT, NOMBRE, VIGENCIA )<br />

VALUES ( 12657378, ‘MARIO CISTERNA’, ‘S’);<br />

El siguiente ejemplo muestra la inserción por medio <strong>de</strong> una Sub<strong>consultas</strong>.<br />

INSERT INTO CHOFER<br />

(RUT, NOMBRE, TELEFONO, DIRECCION, VIGENCIA)<br />

SELECT RUT, NOMBRE, TELEFONO, DIRECCION, VIGENCIA<br />

FROM DUENO WHERE VIGENCIA = ‘S’<br />

177


B. Indices B+<br />

178<br />

Los índices B + son índices multiniv<strong>el</strong>, que contienen n punteros P1, P2, … Pn<br />

y que pue<strong>de</strong>n contener hasta n-1 claves <strong>de</strong> búsqueda K1, K2, … Kn-1. Los valores<br />

<strong>de</strong> las claves <strong>de</strong> búsqueda se mantienen or<strong>de</strong>nados, así si i < j entonces Ki < Kj.<br />

Nodos Hoja: <strong>para</strong> i = 1, 2, … , n-1 <strong>el</strong> puntero Pi apunta a un registro <strong>de</strong> la tabla<br />

con clave Ki o a un cajón <strong>de</strong> punteros cada uno <strong>de</strong> los cuales apuntan a registros<br />

con clave Ki que se utiliza sólo si la clave <strong>de</strong> búsqueda no forma una clave<br />

primaria y <strong>el</strong> archivo no está or<strong>de</strong>nado según la clave <strong>de</strong> búsqueda. Está permitido<br />

que los nodos hojas guar<strong>de</strong>n a lo menos ⎡(n-1)/2⎤ valores, los rangos en cada hoja<br />

no se solapan, así si Li < Lj son nodos hojas y i < j entonces cada valor <strong>de</strong><br />

búsqueda <strong>de</strong> Li es menor que cada valor <strong>de</strong> Lj. El puntero Pn apunta al siguiente<br />

nodo hoja en <strong>el</strong> or<strong>de</strong>n <strong>de</strong> la clave <strong>de</strong> búsqueda, eso permite un mejor <strong>de</strong>sempeño<br />

en búsquedas secuenciales.<br />

Nodos Internos: Los nodos internos tienen la misma estructura que los nodos<br />

hoja, excepto que todos los punteros son punteros a nodos <strong>de</strong>l árbol. Cada nodo<br />

pue<strong>de</strong> guardar hasta n punteros y <strong>de</strong>be guardar a lo menos ⎡n/2⎤ punteros. El<br />

número <strong>de</strong> punteros <strong>de</strong> un nodo se llama grado <strong>de</strong> salida <strong>de</strong>l nodo.<br />

Si un nodo tiene m punteros, <strong>para</strong> i = 2, … m-1, <strong>el</strong> puntero Pi apunta al<br />

subárbol que contiene los valores <strong>de</strong> clave <strong>de</strong> búsqueda menores que Ki y<br />

mayores que Ki-1. Pm apunta a la parte <strong>de</strong>l subarbol que contiene los valores <strong>de</strong> la<br />

clave que son mayores o iguales a Km-1 y a su vez P1 apunta a la parte <strong>de</strong>l<br />

subarbol que contiene los valores <strong>de</strong> clave menores o iguales a K1. El requisito <strong>de</strong>


que todos los nodos tengan ⎡n/2⎤ punteros se impone a todos los nodos internos<br />

menos a la raíz.<br />

179<br />

Otro requisito <strong>de</strong> los árboles B + es que estén equilibrados. Es <strong>de</strong>cir, la<br />

longitud <strong>de</strong> cada camino <strong>de</strong>s<strong>de</strong> la raíz hasta un nodo hoja es la misma.<br />

Para procesar una consulta sobre <strong>el</strong> árbol se tiene que recorrer un camino<br />

en <strong>el</strong> árbol <strong>de</strong>s<strong>de</strong> la raíz hasta algún nodo hoja. Si hay K valores <strong>de</strong> la clave <strong>de</strong><br />

búsqueda en e archivo, este camino no será más largo que ⎡log[n/2](K)⎤ En la<br />

práctica sólo se acce<strong>de</strong> a algunos nodos, Generalmente un nodo se construye<br />

<strong>para</strong> tener <strong>el</strong> mismo tamaño que un bloque <strong>de</strong> disco, <strong>el</strong> cual ocupa normalmente<br />

4Kb. Con una clave <strong>de</strong> búsqueda <strong>de</strong>l tamaño <strong>de</strong> 12 bytes y un tamaño <strong>de</strong> puntero<br />

a disco <strong>de</strong> 8 bytes, n está alre<strong>de</strong>dor <strong>de</strong> 200. Incluso con una estimación más<br />

conservadora <strong>de</strong> 32 bytes <strong>para</strong> <strong>el</strong> tamaño <strong>de</strong> la clave <strong>de</strong> búsqueda, n está próximo<br />

a 100.<br />

Con n = 100, si se tiene 1.000.000 <strong>de</strong> la clave <strong>de</strong> búsqueda en la tabla, una<br />

búsqueda necesita solamente ⎡log50(1.000.000)⎤ = 4 accesos a nodos. Por lo tanto<br />

se necesita leer a lo sumo cuatro bloques <strong>de</strong>l disco <strong>para</strong> realizar la búsqueda.<br />

Índices asociativos.<br />

En una organización <strong>de</strong> archivos por asociación se obtiene la dirección <strong>de</strong>l<br />

bloque <strong>de</strong> disco mediante <strong>el</strong> cálculo <strong>de</strong> una función <strong>de</strong> asociación sobre <strong>el</strong> valor <strong>de</strong><br />

la clave <strong>de</strong>l registro. Se utiliza <strong>el</strong> término cajón (bucket) <strong>para</strong> indicar una unidad <strong>de</strong><br />

almacenamiento que pue<strong>de</strong> guardar uno o más registros. Formalmente, sea K <strong>el</strong><br />

conjunto <strong>de</strong> todos los valores <strong>de</strong> claves <strong>de</strong> búsqueda y sea B <strong>el</strong> conjunto <strong>de</strong> todas<br />

las direcciones <strong>de</strong> cajón, una función <strong>de</strong> asociación h es una función <strong>de</strong> K a B.<br />

Para realizar una búsqueda con valor Ki en la clave <strong>de</strong> búsqueda simplemente se<br />

calcula h(Ki), y luego se busca en <strong>el</strong> cajón al que apunta esa dirección, como<br />

existe la posibilidad <strong>de</strong> que dos claves <strong>de</strong> búsqueda tengan <strong>el</strong> mismo valor <strong>de</strong>


180<br />

asociación, se <strong>de</strong>be buscar luego en <strong>el</strong> cajón las tuplas que coincidan con los<br />

valores <strong>de</strong> búsqueda <strong>de</strong> la clave.<br />

La peor función <strong>de</strong> asociación posible asigna todos los valores <strong>de</strong> la clave<br />

<strong>de</strong> búsqueda al mismo cajón, una función i<strong>de</strong>al es aqu<strong>el</strong>la que distribuye las<br />

claves almacenadas uniformemente a traves <strong>de</strong> los cajones <strong>de</strong> manera que cada<br />

uno <strong>de</strong> estos tenga <strong>el</strong> mismo número <strong>de</strong> registros.<br />

Un índice asociativo (hash in<strong>de</strong>x) organiza las claves <strong>de</strong> búsqueda con sus<br />

punteros asociados <strong>de</strong>ntro <strong>de</strong> una estructura <strong>de</strong> archivo asociativo. Se usa <strong>el</strong><br />

termino índice asociativo <strong>para</strong> <strong>de</strong>notar las estructuras <strong>de</strong> archivo asociativo, asi<br />

como los índices secundarios asociativos. En rigor, los índices asociativos son<br />

sólo estructuras <strong>de</strong> índices secundarios.<br />

Para más referencias se recomienda consultar [Silberschatz97] capítulo 11<br />

(In<strong>de</strong>xación y Asociación) y [Comer79].


C. Métodos <strong>de</strong> almacenamiento <strong>de</strong> Datos.<br />

181<br />

En la mayor parte <strong>de</strong> los sistemas informáticos hay varios tipos <strong>de</strong><br />

almacenamiento <strong>de</strong> datos. Estos medios <strong>de</strong> almacenamiento se pue<strong>de</strong>n clasificar<br />

por la v<strong>el</strong>ocidad con que se pue<strong>de</strong> tener acceso a los datos, por <strong>el</strong> costo <strong>de</strong><br />

adquisición <strong>de</strong>l medio y por la fiabilidad <strong>de</strong>l medio.<br />

La clasificación más general y la que se presentará a continuación es una mezcla<br />

entre las medidas <strong>de</strong> v<strong>el</strong>ocidad y la fiabilidad <strong>de</strong>l medio.<br />

Almacenamiento Primario.<br />

• Caché: La forma <strong>de</strong> almacenamiento más rápida y más costosa, se<br />

gestiona por hardware.<br />

• Memoria Principal : Es <strong>el</strong> medio don<strong>de</strong> operan las instrucciones <strong>de</strong><br />

maquina y los datos disponibles <strong>para</strong> los programas, este tipo <strong>de</strong><br />

almacenamiento es voluble a fallos.<br />

• Memoria Flash: (Ellectrically Erasable Programmable Read Only Memory)<br />

EEPROM, medio <strong>de</strong> almacenamiento que pue<strong>de</strong> aguantar los fallos<br />

<strong>el</strong>éctricos. La lectura toma menos <strong>de</strong> 100 nanosegundos, pero la escritura<br />

tarda <strong>de</strong> 4 a 10 microsegundos. Se borra por bancos <strong>de</strong> memoria. Este tipo<br />

<strong>de</strong> memoria se ha hecho popular como sustituta <strong>de</strong> discos magnéticos <strong>para</strong><br />

guardar pequeños volúmenes <strong>de</strong> datos.<br />

Almacenamiento secundario (en conexión)


182<br />

• Discos magnéticos: Principal medio <strong>de</strong> almacenamiento a largo plazo que<br />

resiste los fallos <strong>de</strong> energía. Generalmente se guarda toda la base <strong>de</strong> datos<br />

en discos magnéticos, pero <strong>para</strong> tener acceso a los datos hay que<br />

trasladarlos hacia la memoria principal. El almacenamiento en disco se<br />

llama tambien almacenamiento <strong>de</strong> acceso directo dado que los discos<br />

pue<strong>de</strong>n leer en cualquier or<strong>de</strong>n a diferencia <strong>de</strong> los medios <strong>de</strong><br />

almacenamiento secuencial.<br />

Almacenamiento terciario (sin conexión)<br />

• Almacenamiento óptico: CDROM (Compact Disc Read Only Memory) y<br />

WORM (Write Once Read Only memory), permiten la grabación una sola<br />

vez pero no <strong>el</strong> borrado o sobre-escritura.<br />

• Almacenamiento en Cinta: Almacenamiento secuencial comúnmente<br />

utilizado <strong>para</strong> respaldos <strong>de</strong> la información puesto que es más lento tanto en<br />

lecturas como escrituras.<br />

C.1. Discos Magnéticos.<br />

Los discos magnéticos proporcionan la parte principal <strong>de</strong>l almacenamiento<br />

secundario <strong>de</strong> los SGBD. La capacidad <strong>de</strong> almacenamiento <strong>de</strong> un sólo disco varía<br />

actualmente <strong>de</strong>s<strong>de</strong> los 10 Mb hasta los 100 Gb. Una Base <strong>de</strong> datos comercial<br />

gran<strong>de</strong> típicamente pue<strong>de</strong> necesitar <strong>de</strong>cenas o centenas <strong>de</strong> discos.<br />

Físicamente, un disco esta compuesto por platos, cada plato es <strong>de</strong> metal o vidrio<br />

cubierto por un material magnético, giran a 60, 90 o 120 Revoluciones por<br />

segundo. La superficie se divi<strong>de</strong> lógicamente en pistas y las pistas en sectores.


183<br />

Cada cara <strong>de</strong>l plato tiene una cabeza <strong>de</strong> lectura escritura, cada una <strong>de</strong> estas<br />

cabezas están montadas en un dispositivo llamado brazo <strong>de</strong>l plato. Al conjunto <strong>de</strong><br />

pistas i-ésimas <strong>de</strong> cada plato se le <strong>de</strong>nomina cilindro.<br />

Una unidad controladora <strong>de</strong> disco es una interfaz entre <strong>el</strong> sistema informático y <strong>el</strong><br />

hardware. Esta unidad acepta or<strong>de</strong>nes <strong>de</strong> alto niv<strong>el</strong> <strong>para</strong> leer o escribir en un<br />

sector e inicia las acciones tales como <strong>de</strong>splazar <strong>el</strong> brazo <strong>de</strong> disco a la pista<br />

a<strong>de</strong>cuada o leer y/o escribir los datos. Un controlador <strong>de</strong> disco posee a<strong>de</strong>más una<br />

unidad <strong>de</strong> comprobación <strong>de</strong> suma (checksum) <strong>para</strong> cada sector que se escribe,<br />

cuando se vu<strong>el</strong>ve a leer un sector <strong>de</strong> disco se vu<strong>el</strong>ve a calcular la suma a partir <strong>de</strong><br />

los datos recuperados y se com<strong>para</strong> con la suma <strong>de</strong> comprobación guardada; si<br />

los datos se han <strong>de</strong>teriorado, resulta muy probable que las sumas no coincidan, si<br />

este es <strong>el</strong> caso, <strong>el</strong> controlador volverá a intentar varias veces la lectura; si <strong>el</strong> error<br />

persiste <strong>el</strong> controlador informará al sistema <strong>de</strong> un fallo <strong>de</strong> lectura.<br />

Un disco se conecta a un sistema informático o a un controlador por medio <strong>de</strong> una<br />

conexión <strong>de</strong> alta v<strong>el</strong>ocidad, su<strong>el</strong>e utilizarse la Interfaz <strong>de</strong> conexión <strong>para</strong> sistemas<br />

informáticos pequeños (Small Computer-System Interconnect Interface, “escasi”)<br />

sin embargo los sistemas <strong>de</strong> alto rendimiento su<strong>el</strong>en disponer <strong>de</strong> un bus más<br />

rápido <strong>para</strong> conectarse a los discos (fibra u otro medio combinado).<br />

C.1.1. Medidas <strong>de</strong> rendimiento <strong>para</strong> los discos.<br />

Las principales medidas <strong>de</strong> la calidad <strong>de</strong> un disco son la capacidad, <strong>el</strong> tiempo <strong>de</strong><br />

acceso, la v<strong>el</strong>ocidad <strong>de</strong> transferencia y la fiabilidad.<br />

• Tiempo <strong>de</strong> búsqueda. Tiempo que le toma al disco <strong>de</strong>splazar <strong>el</strong> brazo <strong>para</strong><br />

que se ubique sobre la pista correcta.


184<br />

• Tiempo medio <strong>de</strong> búsqueda. Media estadística <strong>de</strong> los tiempos <strong>de</strong><br />

búsqueda medido en una sucesión <strong>de</strong> búsquedas aleatorias uniformemente<br />

distribuidas y que es aproximadamente 1/3 <strong>de</strong>l peor <strong>de</strong> los tiempos (2 a 30<br />

milisegundos)<br />

• Tiempo <strong>de</strong> latencia rotacional. Tiempo transcurrido hasta que aparece <strong>el</strong><br />

sector que se <strong>de</strong>sea bajo la cabeza <strong>de</strong> lectura/escritura.<br />

• Tiempo <strong>de</strong> Acceso. Tiempo medio <strong>de</strong> búsqueda + tiempo <strong>de</strong> latencia<br />

rotacional.<br />

• V<strong>el</strong>ocidad <strong>de</strong> transferencia <strong>de</strong> datos. V<strong>el</strong>ocidad a la que se pue<strong>de</strong>n<br />

recuperar o guardar datos luego <strong>de</strong>l tiempo <strong>de</strong> acceso.<br />

• Tiempo medio entre fallos. Cantidad <strong>de</strong> tiempo que se pue<strong>de</strong> esperar que<br />

<strong>el</strong> sistema funcione <strong>de</strong> manera continua sin tener que fallar (entre 30.000 a<br />

800.000 horas)

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!