Tengo una tabla de base de datos que representa una jerarquía de archivos y directorios, con la siguiente estructura (simplificada):enfoque eficiente para la actualización masiva de una tabla jerárquica
ItemId int Path text Type int (0 for files, 1 for directories) ParentId int BackupTime datetime
Actualmente la columna de la BackupTime
sólo se utiliza para archivos , está configurado como nulo para directorios.
Ahora necesito completar esta columna también para los directorios: debe ser el mínimo BackupTime
de todos los descendientes (archivos y directorios).
Esta consulta (ingenua e ineficiente) ilustra lo que quiero hacer:
update Items i
set BackupTime = (select min(BackupTime)
from Items d
where d.Path like i.Path || '%'
and d.Type = 0)
where i.Type = 1
Mi problema es que me parece que no puede encontrar un enfoque eficiente. La consulta anterior lleva demasiado tiempo en grandes volúmenes de datos (esta tabla contiene a menudo más de 100K filas)
Probablemente sería más rápido para buscar las min(BackupTime)
solamente en los niños directos:
update Items i
set BackupTime = (select min(BackupTime)
from Items d
where d.ParentId = i.ItemId)
where i.Type = 1
Pero para esto Para trabajar, debo asegurarme de que los descendientes se actualizarán antes que sus antepasados, así que debo recorrer la jerarquía recursivamente desde abajo hacia arriba. El problema es que no tengo una manera fácil de saber qué elementos son los más profundos en la jerarquía. Estoy usando SQLite, así que no puedo usar consultas jerárquicas.
¿Alguna idea sobre cómo hacer esto de manera eficiente?
Idealmente, yo preferiría ser capaz de hacerlo de una sola consulta de actualización, pero si no es posible, estoy abierto a otras opciones, siempre y cuando sean eficientes
¡Gracias, lo intentaré! –
OK, tomó 5 segundos procesar una base de datos con 100000 elementos ... eso es bastante bueno;).Intenté con una base de datos "ficticia", así que necesito verificar con una verdadera para estar seguro, pero estoy seguro de que tendrá un rendimiento similar. Por cierto, la última condición con 'no existe' no es necesaria: si hay un valor nulo,' min' simplemente devolverá nulo, por lo que eventualmente dará el mismo resultado, con menos iteraciones (14 en lugar de 27 en mi prueba) –
MIN devolverá NULL si los valores * only * son NULL. MIN NO devolverá NULL si se agregan NULL y otros valores. NO EXISTE es necesario para garantizar que las iteraciones van de abajo hacia arriba. Si eliminas NO EXISTE, obtienes resultados incorrectos. Supongamos/dir1/contiene dos elementos: 1) un archivo con BackupTime 4/12 y 2) un directorio/dir2/que contiene 1 archivo con el tiempo de copia de seguridad 4/9. Sin NOT EXISTS,/dir1/obtendrá un BackupTime incorrecto de 4/12 durante la primera iteración. Con NOT EXISTS, esperará hasta la próxima iteración. Las pocas iteraciones que vea sugieren estas respuestas incorrectas. –