Almacenamiento y Recuperación de la Información Técnicas de Indexación Indices Dinámicos 2do Semestre 2005 Wenceslao Palma M. <[email protected]> www.inf.utfsm.cl/~wpalma/ari Indices Dinámicos Indices tipo árbol B Al ser ocupado como estructura de índice no es necesario almacenar el registro en el nodo, basta con la clave y un puntero. La estructura de un nodo es la siguiente: P1 K1 PTR1 P2 K2 PTR2 P3 K3 PTR3 ....... Pn fb=3 Arbol B+ Es una variación de un Arbol B, posee las mismas características pero se distingue en dos aspectos: En los nodos hoja se encuentran las referencias a los archivos de datos. En los nodos intermedios se almacenan las claves que corresponden al mayor valor que se puede alcanzar a través del sub-árbol izquierdo de la clave. 7 3 1 3 6 9 5 6 7 8 9 10 Esta alternativa de indexación es importante ya que permite la posibilidad de dar un mejor soporte a consultas basadas en rangos o categorías y ser una alternativa más eficiente que un índice basado en árbol B y que la combinación Ordenamiento Externo y Mezcla + Búsqueda Binaria. Incluso es posible construir un índice B+ Clusterizado. En el caso de PostgreSQL existe la instrucción CLUSTER indexname ON tablename 7 3 1 3 6 9 5 6 7 8 9 10 En PostgreSQL existe la posibilidad de definir qué tipo de índices utilizar: b-tree (Leghman Yao High-Concurrency b-tree) r-tree (Guttman's quadratic split algorithm) GiST (Generalized Search Tree) hash (Litwin's linear hashing) Ejercicio: Se tiene un archivo de 200000 registros cada uno de 250 bytes. Justifique cual es la mejor elección, para la recuperación de registros, si se desea construir un índice sobre la clave del archivo (9 bytes)? Para realizar la justificación considere índice basado en arbol B (punters de 3 bytes).. índice primario. un disco de 3600 RPM, 18ms (seek) y 1229 bytes/ms, bloques de 1KB. Caso 1: Indice primario área de datos factor de bloqueo: 1024/250 = 4 cantidad ded bloques : 200000/4 = 50000 área de índice entradas: 50000 factor de bloqueo: 1024/11=93 cantidad de bloques: 50000/93= 538 accesos (área de índice + área de datos): log2(538) + 1=11 tiempo de recuperación, considerando que todos los accesos son en disco: 11(18+8.3+(1024/1229))= 298.5ms Caso 2: Arbol B orden del árbol 3p+(9+3)(p-1) <=1024 p<= 69.06667 p = 69 con 3 niveles es suficiente. accesos : 3 + 1= 4 tiempo de recuperación, considerando que todos los accesos son en disco: 4(18+8.3+(1024/1229))= 108.5 ms Por lo tanto conviene usar árbol B. Ejercicio: Considere un archivo de 30000 registros, cada uno de los cuales tiene un tamaño de 100 bytes. La clave de cada registro es de 9 bytes El disco en donde se almacenará tiene bloques de 512 bytes. Cuantos accesos a disco se necesitan si se desea recuperar registros usando un índice basada en un árbol B+ cuyos nodos se llenarán a un 69% de su capacidad? Puntero a nodo es de 6 bytes y el puntero a registro es de 7 bytes. Para el análisis considere las operaciones de : scan completo, búsqueda por igualdad y búsqueda por rango. Indices Hashing Indice basado en hashing extendido. Para buscar k mod 2d 000 001 010 011 100 101 110 111 8 32 64 128 9 17 65 26 ..... 54 38 14 30 7 31 47 71 ..... Indice basado en hashing lineal. Es una alternativa al hashing extendible. No es necesario el uso de un directorio. Comienza con 2d buckets, donde d es el número de bits utlizados para determinar la pertenencia a un bucket. La cantidad ded buckets crece gradualmente. El incremento en la cantidad de buckets puede ser gatillado por la existencia de overflow o cuando se ha alcanzado un factor de carga. El factor de carga fc es el número de registros almacenados dividido por el número de posibles ubicaciones de almacenamiento. El número inicial de buckets n es una potencia de 2, pero su creciemiento no siempre es en base a una potencia de 2. El número de ubicaciones de almacenamiento s=#buckets * #reg/bucket El número inicial de registros r es 0, y se incrementa cuando se inserta un registro. El factor de carga fc = r/s = r/(n*#reg/bucket) Generalmente si fc >= 90% el espacio de almacenamiento se debe incrementar. Algoritmo de inserción se inserta un registro con clave K solo cuando se ha calculado el valor de la función de transformación H se toman los últimos d dígitos de H, recordar que d es la cantidad de dígitos usada para determinar la pertenencia a un bucket. buscar el bucket m donde K debería ser almacenada. si m<n, entonces existe un bucket para almacenar K, si el bucket no tiene espacio usar un bucket de overflow. si m>=n, entonces almacenar K en el bucket m-2d-1 luego de cada inserción chequear si fc < umbral si fc >= umbral entonces incrementar el espacio de almacenamiento (split) considerando lo siguiente: agregar un nuevo bucket (esto podría incrementar d). redistribuir los registros entre el nuevo bucket n=1b2...bd y el bucket 0b2...bd Ejemplo: considere que el valor H está compuesto de 4 dígitos binarios. Inicialmente se almacenan 0000, 1010 y 1111. n=2, d=1, fb=2, r=3 0000 0 1010 1111 1 insertar 0101 0000 0 1010 1111 1 0101 luego de la inserción el fc=4/4 = 100% --> split! Se agrega el nuevo bucket 10 y se dividen los registros de buckets 00 y 10 00 d=2 n=3 r=4 1111 0101 10 1010 01 Insertar 0001. 01<10, pero el bucket no tiene espacio --> bucket de overflow d=2 n=3 r=5 0000 00 0000 1111 01 0101 10 1010 0001 Insertar 0111. pero 11>10, entonces se ubica 0111 en el bucket m-2d-1=11-10=01 d=2 n=3 r=6 00 0000 1111 01 0101 10 1010 0001 0111 luego de la inserción el fc=6/6 = 100% --> split! Se agrega el nuevo bucket 11 y se dividen los registros de buckets 01 y 11 d=2 n=4 r=6 00 0000 0001 0101 10 1010 01 11 0111 1111 Indices Bitmap Indice Valor-Lista de un componente Corresponde a un cjto de bitmaps, uno por cada valor del dominio del atributo indexado. Cada bitmap tiene una cantidad de bits equivalente al número de registros del archivo que se esté indexando, de modo que cada bit represente un registro según la posición relativa que ambos tengan dentro del archivo o del índice, según corresponda. El i-ésimo bit valdrá 1 si el i-ésimo registro del archivo tiene el valor v en el campo de indexación. A continuación se muestra el contenido de 9 bitmaps que indexan un atributo con dominio [0..8] Columna 3 2 1 2 8 2 2 0 7 5 B8 0 0 0 0 1 0 0 0 0 0 B7 0 0 0 0 0 0 0 0 1 0 B6 0 0 0 0 0 0 0 0 0 0 B5 0 0 0 0 0 0 0 0 0 1 B4 0 0 0 0 0 0 0 0 0 0 B3 1 0 0 0 0 0 0 0 0 0 B2 0 1 0 1 0 1 1 0 0 0 B1 0 0 1 0 0 0 0 0 0 0 B0 0 0 0 0 0 0 0 1 0 0 Indice Valor-Lista de n componentes Para disminuir la memoria utilizada se puede realizar una representación en alguna base numérica que requiera menos bits. Considerando el caso anterior se puede tener una representación en base 3 para bajar de 9 a 6 bitmaps, teniendo dos componentes de bitmaps para hacer el almacenamiento. Si el valor a indexar es 8, se puede expresar como 2x3+2, esto indica que en ambos componentes se setea el bit 2. Si el valor a indexar es 7, se puede expresar como 2x3+1, esto indica que se setea el bit 2 en el segundo componente y el bit 1 en el primer componente. 3 2 1 2 8 2 2 0 7 5 B2 0 0 0 0 1 0 0 0 1 0 B1 B 0 1 0 0 1 0 1 0 1 0 0 0 1 0 1 0 1 0 0 1 0 B2 0 1 0 1 1 1 1 0 0 1 B1 0 0 1 0 0 0 0 0 1 0 B0 1 0 0 0 0 0 0 1 0 0 Indice codificado por rangos de 1 componente En un esquema de igualdad (valor-lista de 1 componente), se tienen b bitmaps según sea el tamaño del dominio del campo de indexación. En un esquema codificado por rangos, también hay b bitmaps pero la representación de un valor v tiene un valor cero en los v bitmaps “más a la derecha” y un valor uno en los restantes bitmaps (los que están más a la izquierda). Columna 3 2 1 2 8 2 2 0 7 5 B8 1 1 1 1 1 1 1 1 1 1 B7 1 1 1 1 0 1 1 1 1 1 B6 1 1 1 1 0 1 1 1 0 1 B5 1 1 1 1 0 1 1 1 0 1 B4 1 1 1 1 0 1 1 1 0 0 B3 1 1 1 1 0 1 1 1 0 0 B2 0 1 1 1 0 1 1 1 0 0 B1 0 0 1 0 0 0 0 1 0 0 B0 0 0 0 0 0 0 0 1 0 0 Indice bit-sliced Un índice bit-sliced de un atributo es una proyección de los bits que componen los valores de dicho atributo. Si el atributo A de cierto archivo está definido como un entero de 2 bytes, el índice bit-sliced estará compuesto de 16 bitmaps. Si el valor es 201 cuya representación binaria es 0000000011001001 B15..B10 B B B B B B B B B B 9 8 7 6 5 4 3 2 1 0 201 0...0 0 0 1 1 0 0 1 0 0 1 También es posible construir un índice de n componentes y otro codificado por rangos. En el caso de n componentes, si la base es 10, el 201 se puede escribir como 2x102 + 0x10 + 1 Criterios para la selección de índices El diseño físico de una BD tienen como actividad la elección de las estructuras de almacenamiento y formas de acceso a los datos, con el objetivo de obtener un buen rendimiento. Al momento del diseño físico es importante considerar: Tiempo de respuesta: desde la entrada del proceso hasta la respuesta. Espacio en disco: dimensionar el espacio requerido. Rendimiento del sistema: throughput. La tareas necesarias son: Analizar las consultas sobre los datos : archivos involucrados, atributos sobre los cuales existen condiciones de selección, atributos sobre los cuales hay condiciones de selección que involucran a registros de otros archivos. Análisis de frecuencia esperada de la invocación de la consulta Análisis de posibles restricciones de tiempo de las consultas. Análisis de la frecuencia esperada de operaciones de actualización. Método para realizar el diseño físico de una BD Una opción común es mantener los registros desordenados y crear muchos índices secundarios sobre atributos que se utilizan para operaciones de búsqueda y join. Otra alternativa es: escoger un atributo usado frecuentemente y definirlo como campo de ordenamiento para crear un índice primario o agrupado (según corresponda) sobre él. por cada atributo, que no es el campo de ordenamiento, y que es frecuentemente utilizado en operaciones de búsqueda y join, especificar un índice secundario. si las actualizaciones son muy frecuentes se debe reducir el número de índices. si un atributo es usado frecuentemente en operaciones de búsqueda y join pero no para recuperar registros en orden, un archivo tipo hashing puede ser utilizado, de lo contrario se puede usar árbol b+.