Búsqueda binaria o problema de actualización del índice Btree

votos
4

Imagine que le entregan un nuevo libro todos los días de un autor. El libro es un trabajo en progreso. Él no te dice lo que ha cambiado o agregado.

Su trabajo es identificar los cambios y las adiciones, y pasar ÚNICAMENTE estos a la editorial (que no tiene tiempo para leer el libro completo todos los días)

A los efectos de este problema, el libro está compuesto por 1m de líneas de texto ascii y en crecimiento (en realidad, un archivo de copia de seguridad MySQL).

Mi idea actual es hacer un hash seguro (SHA256 por ejemplo) de cada línea (1k Chars) y almacenarlo en HD. Como el hash tiene solo 32 bytes, el archivo solo tiene 32 MB.

Luego, cuando obtengamos el siguiente archivo mañana, lo revisamos línea por línea, creando un nuevo hash para cada línea y comparándolo con el hash del día anterior.

Cuando el proceso finaliza, sobrescribimos el archivo hash listo para el día siguiente.

La comparación usa un método de búsqueda binario de comparación de cadenas (> <operandos) Esto devuelve un resultado en un promedio de cuatro iteraciones.

Todavía no he codificado una solución de índice btree, pero ¿cómo abordaría esto?

Publicado el 30/10/2008 a las 01:52
fuente por usuario
En otros idiomas...                            


6 respuestas

votos
1

Yo usaría diff .

Si tuviera que implementarlo dentro de mi propio programa, usaría uno de los algoritmos para encontrar la subsecuencia común más larga de dos secuencias, tratando cada archivo como una secuencia de líneas.

Respondida el 30/10/2008 a las 01:58
fuente por usuario

votos
0

"Luego, cuando obtengamos el siguiente archivo mañana, lo revisaremos línea por línea, creando un nuevo hash para cada línea y comparándolo con el hash del día anterior".

Entendido: 1m de líneas de los valores hash de hoy en comparación con las líneas de 1m de los valores de ayer.

¿Las líneas se insertan o eliminan? Si no, este es un conjunto simple de lecturas paralelas para ver si los hash son diferentes.

Si hay adiciones o eliminaciones, deberá usar el algoritmo diff para determinar el alcance del cambio.

Todo está bien. No es muy difícil de implementar.

En ese contexto, lo siguiente no tiene sentido.

La comparación usa un método de búsqueda binario de comparación de cadenas (> <operandos) Esto devuelve un resultado en un promedio de cuatro iteraciones.

¿Hay algún tipo de orden para los valores hash? O alguna estructura de árbol?

Respondida el 30/10/2008 a las 02:20
fuente por usuario

votos
0

Un libro de 1 millón de líneas es enorme: quizás haya entre 30 y 50 líneas por página, así que seamos generosos y asumamos 100 líneas por página, lo que significa 10.000 páginas en el libro.

Las líneas de 1 KB también son mucho más grandes de lo normal; la legibilidad básica no sugiere que haya muchos personajes por línea. ¿Tiene la intención de hacer hash de líneas de hasta 1 KB o dividir el archivo en fragmentos de 1 KB? Un problema con su esquema es que cualquier línea repetida tendría un hash repetido; nunca podría identificar cuándo se agregó o eliminó una de esas líneas.

Es de suponer que también deberá notificar al editor de las líneas eliminadas.

Al igual que con Glomek, usaría diffen el archivo. Si mantiene el archivo bajo el control RCS o CVS, solo tendría almacenada la versión actual del archivo y las diferencias entre las versiones anteriores. Con esto, usted podría proporcionar diferencias acumuladas durante una semana o un mes también.

Y probablemente no desarrollaría mi propia indexación de B-Tree.

Respondida el 30/10/2008 a las 02:23
fuente por usuario

votos
0

la solución que describes es algo similar al algoritmo rsync. Un punto importante es que rsync debe reconocer los fragmentos existentes en cualquier parte del archivo de destino, en cualquier desplazamiento desde el original.

Si sus archivos están realmente estructurados por registros, puede simplificar un poco como usted propone. si no, necesitas una suma de comprobación progresiva.

también, ¿tienes que reconocer reordenamientos? o solo inserciones / eliminaciones / reemplazos?

el caso más genérico es el algoritmo completo de rsync, que dice lo siguiente:

  • definición de parámetros:

    1. elija un tamaño de bloque 512, o 1k generalmente funciona bien.
      • elige una suma de comprobación 'fuerte'. algo así como MD4 más o menos. 64bits son suficientes.
      • elija una suma de comprobación móvil "débil". uno que le permite 'restar' el byte de la cola y 'agregar' un byte de la cabeza para obtener la suma de comprobación de un bloque de 1 byte hacia adelante. por lo general, una suma de comprobación de 16 bits funciona bien.
  • firma del archivo antiguo:

    1. atraviesa todo el archivo antiguo, en cada bloque calcula sumas de comprobación débiles y fuertes. con sumas de comprobación de 16 y 64 bits y bloques de 512 bytes, lo que significa 10 bytes por bloque o 20 KB por megabyte. esta es la 'firma'
  • crear 'parche' con nuevo archivo y firma del archivo anterior:

    1. cargar la firma del archivo anterior, lo mejor es una tabla hash, con las sumas de comprobación débiles como claves, las sumas de comprobación fuertes y la posición del bloque son los valores.
      • lee el primer bloque del nuevo archivo
      • calcular la suma de comprobación débil del bloque cargado
      • revisa la tabla hash para ver si la suma de comprobación débil está allí.
      • si se encuentra, calcule la suma de comprobación fuerte y compárela con la que se encuentra en el hash
      • si ambas sumas de comprobación coinciden, marque como 'lo obtuve' con la referencia de bloque en el hash, avance un bloque de tamaño completo y vuelva al paso 3
      • si la suma de comprobación fuerte no coincidía, o si la suma de comprobación débil no estaba en el hash, 'roll' la suma de comprobación débil, es decir, 'agregar' el siguiente byte después del bloque, y 'restar' el primer byte del cola.
      • agregue el byte 'substracted' de la cola a la lista de 'nuevos' bytes en el parche
      • vuelve al paso 4
  • aplicar parche al archivo anterior

    1. el 'parche' es la lista de 'nuevos' bytes que cayeron al pasar la suma de verificación, más la lista de bloques 'conseguidos' que coinciden en el archivo anterior.
Respondida el 30/10/2008 a las 02:34
fuente por usuario

votos
0

Esta es una técnica utilizada para la carga incremental en un almacén de datos. En la situación en la que no tiene la capacidad de identificar los datos modificados dentro de un sistema fuente, puede tomar una instantánea de los datos y compararlos con su última instantánea para identificar las diferencias. Esta técnica incluso recibe una mención en el libro de Ralph Kimball sobre el tema y se utiliza en una aplicación en la que participé en el diseño de.

Necesita un algoritmo hash con una clave muy amplia, ya que este enfoque es vulnerable a los ataques de cumpleaños . MD5 o cualquiera de la familia SHA sería bueno. Tampoco puede detectar eliminaciones sin un proceso posterior que atraviese la diferencia buscando claves naturales que faltan. Este cálculo realmente necesita conocer la estructura de la tabla.

Respondida el 30/10/2008 a las 09:44
fuente por usuario

votos
0

Un problema con su esquema es que cualquier línea repetida tendría un hash repetido; nunca podría identificar cuándo se agregó o eliminó una de esas líneas

Muy buen punto, pero no es un problema. Una línea repetida es un duplicado y todos los duplicados se eliminan en la siguiente etapa de procesamiento. Entonces sí, tienes razón, pero no es un problema.

El enlace "diff" me lleva a una página con una descripción de lo que supongo que es una aplicación. No hay ningún enlace de descarga, no hay código en ningún idioma ... ¿Qué me falta aquí?

Algunos de ustedes han hablado sobre la granularidad a nivel de bytes. Esto no es necesario solo se requiere granularidad a nivel de línea porque si se ha cambiado algo en la línea, toda la línea (registro) debe reprocesarse debido a que cualquier cambio dentro de la línea afecta a toda la línea.

Así que estamos comparando líneas de aproximadamente 1000 caracteres (sin binario), en dos archivos (instantánea de hoy e instantánea de ayer) que son cada uno de aproximadamente 1m de líneas.

Entonces, usando un hash seguro como SHA256 (MD5 tiene colisiones y es lento en comparación) puedo procesar unos 30MB / seg en mi computadora portátil HO. El servidor, por supuesto, masticará mucho más rápido.

Por lo tanto, si el archivo es de 1 GB, entonces hacer todas las acciones toma alrededor de 33 segundos, y leer un archivo de 1 Gb usando la memoria de la página de Windows toma alrededor de 30 segundos. No es horrible

Ahora tenemos dos matrices de hash que representan las líneas en cada archivo. Si los clasificamos, ahora podemos utilizar una búsqueda binaria, por lo que iteramos a través de los nuevos hash de archivos buscando una coincidencia en los hashs de los archivos antiguos. Si no lo encontramos, esa línea se agrega al archivo de cambios.

Tenga en cuenta que el libro de líneas (base de datos heredada) es desconocido en todos los aspectos. No hay garantía de orden de líneas, ubicación de cambios, tipo de cambios.

Las sugerencias de leer página por página son buenas, pero se supone que los dos archivos están en orden hasta el primer cambio. Esto no puede ser asumido. Las líneas (filas) podrían estar en cualquier orden. Además, la elección de un tamaño de bloques arbitrario infringe la granularidad de una línea. Para los fines de esta tarea, las líneas son inmutables.

Desde ese excelente enlace sobre la carga de invrementa: Captura de comparación de archivos: este método también se conoce como el método diferencial de instantáneas. Este método funciona manteniendo las imágenes del antes y el después de los archivos que son de interés para el almacén de datos. Los registros se comparan para encontrar cambios y las claves de registro se comparan para encontrar inserciones y eliminaciones. Esta técnica es la más adecuada en el caso de los sistemas heredados debido a que los desencadenantes generalmente no existen y los registros de transacciones son inexistentes o están en un formato propietario. Dado que la mayoría de las bases de datos heredadas tienen algún mecanismo para volcar datos en archivos, esta técnica crea instantáneas periódicas y luego compara los resultados para generar registros de cambios. Ciertamente, todos los problemas de captura estática están presentes aquí. El desafío de comparar filas completas de información y la identificación y coincidencia de claves introduce una complejidad añadida. Esta técnica es de naturaleza compleja y, por lo general, no es deseable, pero, en algunos casos, puede ser la única solución.

Esto es más relevante aquí: a medida que avanzamos en el ámbito de los almacenes de datos de terabytes, la capacidad de reconstruir el almacén de datos desde cero cada noche seguirá el camino del dinosaurio. El enfoque lógico y eficiente para actualizar el almacén de datos implica alguna forma de estrategia de actualización incremental.

¿Entonces supongo que estoy en el camino correcto? ¿Un índice btree no daría una ventaja?

Respondida el 31/10/2008 a las 08:47
fuente por usuario

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more