Estoy usando Django y PostgreSQL, pero no estoy absolutamente vinculado al ORM de Django si hay una forma mejor de hacerlo con SQL puro o operaciones específicas de la base de datos.Estructura de datos para almacenar un campo de clasificación para permitir modificaciones de manera eficiente
Tengo un modelo que necesita un orden secuencial. Las operaciones de búsqueda generalmente recuperarán la lista completa en orden. La operación más común en estos datos es mover una fila a la parte inferior de la lista, con un subconjunto de los elementos que intervienen burbujeando para reemplazar el artículo anterior de esta manera:
(operation on A, with subset B, C, E) A -> B B -> C C -> E D -> D E -> A Notice how D does not move.
En general, el subconjunto de artículos no será más de aproximadamente 50 elementos, pero la lista base puede crecer a decenas de miles de entradas.
La forma más obvia de implementar esto es con un campo de orden entero simple. Esto parece poco óptimo. Requiere el compromiso de hacer que la columna de ordenamiento de posición no sea única, donde la no exclusividad solo se requiere para la duración de una operación de modificación. Para ver esto, imagina la operación mínima, con un subconjunto de B:
oldpos = B.pos
B.pos = A.pos
A.pos = oldpos
A pesar de que ha almacenado la posición, en la segunda línea que ha violado la restricción de unicidad. Además, este método hace que la atomicidad sea problemática: su operación de lectura tiene que ocurrir antes de la escritura, y durante ese tiempo sus registros podrían cambiar. La documentación de manejo de transacciones predeterminada de Django no soluciona esto, aunque sé que debería ser posible en el SQL usando el nivel de bloqueo de transacción "REPEATABLE READ".
Estoy buscando estructuras de datos alternativas que se ajusten más a este patrón de uso. He buscado this question para obtener ideas.
Una propuesta no es la solución estilo decimal Dewey, lo que hace que las operaciones de inserción se producen numéricamente entre los valores existentes, por lo que la inserción de una entre B y C resultados en:
A=1 -> B=2 B=2 -> A=2.5 C=3 -> C=3
Esto resuelve la columna singularidad problema, pero introduce el problema de que la columna debe ser un flotante de un número específico de decimales. O sobreestimo y almaceno más datos de los que necesito, o el sistema queda limitado por la longitud decimal arbitraria que impongo. Además, no espero que el uso sea uniforme en la base de datos: algunas claves se moverán con mucha más frecuencia que otras, lo que hará que esta solución llegue al límite antes. Podría resolver este problema periódicamente volviendo a numerar la base de datos, pero parece que una buena estructura de datos debería evitar necesitar esto.
Otra estructura que he considerado es la lista vinculada (y variantes). Esto tiene la ventaja de hacer que la modificación sea sencilla, pero no estoy seguro de sus propiedades con respecto a SQL: ordenar una lista de este tipo en la consulta SQL parece ser dolorosa, y extraer un subconjunto no secuencial de la lista es terrible. propiedades de recuperación.
Más allá de esto, hay B-Trees, varios árboles binarios, y así sucesivamente. ¿Qué recomiendas para esta estructura de datos? ¿Hay una estructura de datos estándar para esta solución en SQL? ¿La idea inicial de ir con enteros secuenciales realmente va a tener problemas de escalado, o estoy viendo problemas donde no los hay?
Lanzando una recompensa aquí debido al bajo número de respuestas ... –
Hola Paul - veo que aceptaste mi respuesta - gracias: D. ¿Con cuáles de las soluciones propuestas decidió ir, y por qué? – Matt