Solución Actividad 2: Técnicas de dispersión 1- Un fichero COMPONENTS con Numcomp como clave de direccionamiento calculado contiene registros con los siguientes valores de Numcomp: 2369, 3760, 4692, 4871, 5659, 1821, 1074, 7115, 1620, 2428, 3943, 4750, 6975, 4981, 9208. El fichero utiliza ocho cubetas, numeradas del 0 a 7. Cada cubeta es un bloque del disco y puede contener dos registros. (a) Cargar estos registros en el fichero en el orden dado, empleando la función de direccionamiento calculado h(K) = K mod 8. Para resolver las colisiones se utiliza la técnica de encadenamiento. (b) Calcular el número medio de accesos a bloques para una recuperación aleatoria basándose en Numcomp. Respuesta: (a) Los registros se colocarán en los siguientes buckets: Rec# rec1 rec2 rec3 rec4 rec5 rec6 rec7 rec8 rec9 rec10 rec11 rec12 rec13 rec14 rec15 K 2369 3760 4692 4871 5659 1821 1074 7115 1620 2428 3943 4750 6975 4981 9208 h(K) 1 0 4 7 3 5 2 3 4 4 7 6 7 5 0 (número de bucket) overflow overflow (b) Dos registros de los 15 están en overflow, por lo que requerirán un acceso a bloque adicional. Los otros registros requieren sólo un acceso. Por lo tanto, el tiempo medio para recuperar un registro aleatorio es: (1 * (13/15)) + (2 * (2/15)) = 0.867 + 0.266 = 1.133 accesos a bloques 2- Cargar los 13 primeros registros del ejercicio 1 en ficheros con direccionamiento calculado extensible, utilizando la función de dispersión (hash) h(K) = K mod 32. Mostrar las estructuras de directorio en cada paso, y las profundidades locales y globales. Rec# record1 record2 record3 record4 record5 record6 record7 record8 record9 record10 record11 record12 record13 record14 record15 K 2369 3760 4692 4871 5659 1821 1074 7115 1620 2428 3943 4750 6975 4981 9208 h(K) (bucket number) 1 16 20 7 27 29 18 11 20 28 7 14 31 21 24 Binary h(K) 00001 10000 10100 00111 11011 11101 10010 01011 10100 11100 00111 01110 11111 10101 11000 Respuesta: Paso 1: introducir record1 y record2 Paso 2: introducir record3 y record4 Paso 3: introducir record5 y record6 Paso 4: introducir record7 Paso 5: introducir record8 y record9 Paso 6: introducir record10 Paso 7: introducir record11 y record12 Paso 8: introducir record13 Paso 9: primera operación para introducir record14. Consiste en la división del cubo 101 (donde se produce el overflow) en dos cubos: 1010 y 1011. Paso 10: segunda operación para introducir record14. Se divide el cubo 1010 en dos cubos: 10100 y 10101. Además, se introduce el record15 (en la figura no se muestra, debería estar en la cubeta 110). 2- Cargar los 13 primeros registros del ejercicio anterior en ficheros con direccionamiento calculado lineal. Empezar con un solo bloque de disco, utilizando la función hash h0 = K mod 20, y mostrar cómo crece el fichero y cómo cambian las funciones hash a medida que se insertan registros. Asumir que los bloques se dividen siempre que se produce un desbordamiento, y mostrar el valor n en cada etapa. Respuesta: Inicialmente, el tamaño del fichero es M = 1 bloque FIGURAS 1 y 2: n=0 h0 (record1) = 2369 mod 20 = 0 h0 (record2) = 3760 mod 20 = 0 h0 (record3) = 4692 mod 20 = 0 OVERFLOW ⇒ dividir cubo 0 mediante h1(K) creando el cubo 1 ⇒ n=1 (i.e, hay 1 cubo desdoblado) h1 (record1) = 2369 mod 21 = 1 h1 (record2) = 3760 mod 21 = 0 h1 (record3) = 4692 mod 21 = 0 n = M ⇒ Se ha aplicado h1 a todo el fichero (formado por 1 único bloque, en este caso) ⇒ EXPANSIÓN COMPLETA ⇒ n=0 ⇒ usar h1(K) = K mod 21 FIGURAS 2 y 3: h1 (record4) = 4871 mod 21 = 1 h1 (record5) = 5659 mod 21 = 1 OVERFLOW ⇒ dividir cubo 0 mediante h2(K) creando el cubo 2 ⇒ n=1 (i.e, hay 1 cubo desdoblado) h2 (record2) = 3760 mod 22 = 0 h2 (record3) = 4692 mod 22 = 0 h1 (record6) = 1821 mod 21 = 1 OVERFLOW ⇒ dividir cubo 1 mediante h2(K) creando el cubo 3 ⇒ n=2 (i.e, hay 2 cubos desdoblados) h2 (record1) = 2369 mod 22 = 1 h2 (record4) = 4871 mod 22 = 3 h2 (record5) = 5659 mod 22 = 3 h2 (record6) = 1821 mod 22 = 1 n = M ⇒ Se ha aplicado h2 a todo el fichero (formado por dos bloques 0 y 1) ⇒ EXPANSIÓN COMPLETA ⇒ n=0 ⇒ usar h2(K) = K mod 22 FIGURAS 4 y 5: h2 (record7) = 1074 mod 22 = 2 h2 (record8) = 7115 mod 22 = 3 OVERFLOW ⇒ dividir cubo 0 mediante h3(K) creando el cubo 4 ⇒ n=1 (i.e, hay 1 cubo desdoblado) h3 (record2) = 3760 mod 23 = 0 h3 (record3) = 4692 mod 23 = 4 h2 (record9) = 1620 mod 22 = 0 ⇒ como 0 < n=1 ⇒ el cubo 0 está desdoblado ⇒ debe aplicarse la función h3(K) h3 (record9) = 1620 mod 23 = 4 h2 (record10) = 2428 mod 22 = 0 ⇒ como 0 < n=1 ⇒ el cubo 0 está desdoblado ⇒ debe aplicarse la función h3(K) h3 (record10) = 2428 mod 23 = 4 OVERFLOW ⇒ dividir cubo 1 mediante h3(K) creando el cubo 5 ⇒ n=2 (i.e, hay 2 cubos desdoblados) h3 (record1) = 2369 mod 23 = 1 h3 (record6) = 1821 mod 23 = 5 FIGURAS 6 y 7: h2 (record11) = 3943 mod 22 = 3 OVERFLOW ⇒ dividir cubo 2 mediante h3(K) creando el cubo 6 ⇒ n=3 (i.e, hay 3 cubos desdoblados) h3 (record7) = 1074 mod 23 = 2 h2 (record12) = 4750 mod 22 = 2 ⇒ como 2 < n=3 ⇒ el cubo 2 está desdoblado ⇒ debe aplicarse la función h3(K) = K mod 23 h3 (record12) = 4750 mod 23 = 6 h2 (record13) = 6975 mod 22 = 3 OVERFLOW ⇒ dividir cubo 3 mediante h3(K) creando el cubo 7 ⇒ n=4 (i.e, hay 4 cubos desdoblados) h3 (record4) = 4871 mod 23 = 7 h3 (record5) = 5659 mod 23 = 3 h3 (record8) = 7115 mod 23 = 3 h3 (record11) = 3943 mod 23 = 7 h3 (record13) = 6975 mod 23 = 7 (está en overflow, por lo que se mantiene en la lista de desbordamiento, pero en este caso NO se hace expansión de cubos) n = M ⇒ Se ha aplicado h3 a todo el fichero (formado por cuatro bloques) ⇒ EXPANSIÓN COMPLETA ⇒ n=0 ⇒ usar h3(K) = K mod 23 FIGURA 8: h3 (record14) = 4981 mod 23 = 5 h3 (record15) = 9208 mod 23 = 0 Nota: Es más común establecer una política de desdoblamiento que especifica un factor de carga del fichero que dispara el desdoblamiento del bucket señalado por n (generalmente un porcentaje de carga de los buckets), en vez de realizar el desdoble cada vez que se produce una situación de overflow. El factor de carga l se define como l = r / (bfr * N), donde r es el número actual de registros del fichero, bfr es el número máximo de registros que pueden encajar en un cubo, y N es el número actual de cubos del fichero. Las divisiones se pueden lanzar cuando l es mayor de un cierto umbral (p. ej, 0.9). También es posible combinar bloques (en caso de eliminación de registros) en orden inverso a como fueron creados. Las combinaciones se pueden lanzar cuando la carga cae por debajo de otro umbral (p. ej., 0.7). REALIZACIÓN DE BÚSQUEDAS Para analizar las ventajas de este modelo, a continuación se presenta el modo en que se realizan las búsquedas de registros. Los ejemplos se basan en la situación mostrada en la Figura 7, donde existían 12 registros en el fichero. Pasos a seguir en la búsqueda de un registro con clave k: 1) calcular m=hj(k) 2) si m<n entonces calcular m=hj+1(k) porque el cubo ya está dividido 3) buscar en el cubo con valor de dispersión m (y su zona de desbordamiento, si lo hay) En nuestro caso, n=3, la función de dispersión es h2(k) = k mod 22 y la función de expansión es h3(k) = k mod 23 Ej: búsqueda de r8 m <- h2(r8) = 7115 mod 22 = 3 m=3 no es menor que n=3 buscar en cubo 3 (y su desbordamiento, si lo hay) Ej: búsqueda de r12 m <- h2(4750) = 4750 mod 22 = 2 (m=2) < (n=3) entonces m <- h3(4750) = 4750 mod 23 = 6 buscar en cubo 6 (y su desbordamiento, si lo hay)