Estoy tratando de entender cómo almacenar correctamente la información ordenada en una base de datos relacional.
Un ejemplo:
Digamos que tengo una lista de reproducción, que consta de canciones. Dentro de mi base de datos relacional, tengo una tabla que Playlists
contiene algunos metadatos (nombre, creador, etc.). También tengo una tabla llamada Songs
, que contiene un playlist_id
, así como información específica de la canción (nombre, artista, duración, etc.).
Por defecto, cuando se agrega una nueva canción a una lista de reproducción, se agrega al final. Al realizar el pedido en Song-ID (ascendente), el orden será el orden de adición. Pero, ¿qué pasa si un usuario debería poder reordenar canciones en la lista de reproducción?
Se me ocurrieron algunas ideas, cada una con sus ventajas y desventajas:
- Una columna llamada
order
, que es un número entero . Cuando se mueve una canción, se cambia el orden de todas las canciones entre su posición anterior y la nueva, para reflejar el cambio. El inconveniente de esto es que se deben hacer muchas consultas cada vez que se mueve una canción, y el algoritmo de movimiento no es tan trivial como con las otras opciones. - Una columna llamada
order
, que es un decimal (NUMERIC
). Cuando se mueve una canción, se le asigna el valor de coma flotante entre los dos números adyacentes. Inconveniente: los campos decimales ocupan más espacio y es posible que se quede sin precisión, a menos que se tenga cuidado de redistribuir el rango después de cada pocos cambios. - Otra forma sería tener
previous
unnext
campo que haga referencia a otras canciones. (o son NULL en el caso de la primera y la última canción de la lista de reproducción en este momento; básicamente se crea una lista vinculada ). Inconveniente: las consultas como 'encontrar la X canción en la lista' ya no son de tiempo constante, sino lineal.
¿Cuál de estos procedimientos se usa con más frecuencia en la práctica? ¿Cuál de estos procedimientos es más rápido en bases de datos medianas y grandes? ¿Hay alguna otra forma de archivar esto?
EDITAR: En aras de la simplicidad, en el ejemplo, una canción solo pertenece a una lista de reproducción (una relación de muchos a uno). Por supuesto, también se podría usar una tabla de unión, por lo que la lista de reproducción de canciones es una relación de muchos a muchos (y aplicar una de las estrategias anteriores en esa tabla).
update songorder set order = order - 1 where order >= 12 & order <= 42; update songorder set order = 42 where id = 123;
Son dos actualizaciones, no treinta. Tres si quieres poner una restricción única en orden.
Queries like 'find the Xth Song in the list' are no longer constant-time
también es cierto para la opción 2.