Rápido Relacional método de almacenamiento de datos de árbol (por ejemplo rosca comentarios sobre artículos)

StackOverflow https://stackoverflow.com/questions/846201

Pregunta

Tengo un cms que almacena los comentarios en contra de los artículos.Estos comentarios pueden ser roscados y no roscados.Aunque técnicamente no son lo mismo solo que con la respuesta de la columna de la izquierda en blanco cuando no roscados.Mi aplicación funciona en sqlLite, MySQL y pgsql así que tengo bastante estándar SQL.

Actualmente tengo un comentario de la tabla

comment_id
article_id
user_id
comment
timestamp
thread (this is the reply column)

Mi pregunta es averiguar la mejor manera de representar la rosca comentarios en la base de datos.Tal vez en una tabla independiente que apoya el árbol sin el contenido y una simple tabla para mantener el texto?Tal vez en el camino de lo que ya es?Tal vez de otra manera?

Si los comentarios son de la onu-rosca que fácilmente se puede pedir por la marca de hora.

Si son de rosca I tipo como este

ORDER BY SUBSTRING(c.thread, 1, (LENGTH(c.thread) - 1))

Como se puede ver en la ORDEN, el comentario de las consultas no utilizar nunca un índice como la función de los índices basados en sólo se vive realmente en Oracle.Me ayudará a tener un rayo rápido comentario páginas.

¿Fue útil?

Solución

A mi me gusta cómo resuelve Drupal este problema. Se asigna una ID del tema a cada comentario. Este id comienza en 1 para el primer comentario. Si se añade una respuesta a este comentario, el id 1.1 es asignado a la misma. La respuesta a comentar 1.1.1 se da el ID del tema 1.2. Un hermano de comentario <=> se da el ID del tema <=>. Se entiende la idea. El cálculo de estos identificadores de hilo se puede hacer fácilmente con una consulta cuando se añade un comentario.

Cuando se representa el hilo, todos los comentarios que pertenecen a la rosca se recuperan en una sola consulta, ordenados por el ID del tema. Esto le da a los hilos en el orden ascendente. Por otra parte, utilizando el ID del tema, se puede encontrar el nivel de anidamiento de cada comentario, y una sangría en consecuencia.

1
1.1
1.1.1
1.2
1.2.1

Hay algunas cuestiones a resolver:

  • Si un componente de la ID del tema crece a 2 dígitos, la clasificación por ID del tema no producirá el orden esperado. Una solución fácil es asegurar que todos los componentes de un ID del tema se rellena con ceros para tener la misma anchura.
  • Clasificar por descendiendo ID del tema no produce el orden descendente esperada.

Drupal resuelve el primer problema de una manera más complicada utilizando un sistema de numeración llamado vancode. En cuanto a la segunda cuestión, se resuelve agregando una barra invertida (cuyo código ASCII es superior dígitos) a los ID de hebra al ordenar por orden descendente. Puede encontrar más detalles sobre esta aplicación comprobando el código fuente de la módulo de comentarios (ver el gran comentario antes de la comment_get_thread función).

Otros consejos

Sé que la respuesta es un poco tarde, pero para el árbol de datos utilizan una mesa de cierre http://www.slideshare.net/billkarwin/models-for-hierarchical-data

Describe 4 métodos:

  • lista Adjcency (la clave externa matriz sencilla)
  • enumeración Path (la estrategia de Drupal se menciona en la respuesta aceptada)
  • conjuntos anidados
  • mesa Cierre (almacenar hechos antepasado / descendiente en una relación separada [Tabla], con una columna distancia posible)

La última opción tiene ventajas de las operaciones CRUD fácil en comparación con el resto. El costo es de espacio, que es O (n ^ 2) el tamaño de los nodos número de árboles en el peor de los casos, pero probablemente no es tan malo en la práctica.

Por desgracia, la pura SQL métodos para hacerlo son bastante lenta.

El NESTED SETS propuesto por @Marc W son muy elegantes, pero pueden requerir la actualización de todo el árbol, si tu las ramas de los árboles hit de los rangos, que puede ser bastante lento.

Ver este artículo en mi blog sobre cómo hacerlo rápido en MySQL:

Tendrás que crear una función:

CREATE FUNCTION hierarchy_connect_by_parent_eq_prior_id(value INT) RETURNS INT
NOT DETERMINISTIC
READS SQL DATA
BEGIN
        DECLARE _id INT;
        DECLARE _parent INT;
        DECLARE _next INT;
        DECLARE CONTINUE HANDLER FOR NOT FOUND SET @id = NULL;

        SET _parent = @id;
        SET _id = -1;

        IF @id IS NULL THEN
                RETURN NULL;
        END IF;

        LOOP
                SELECT  MIN(id)
                INTO    @id
                FROM    t_hierarchy
                WHERE   parent = _parent
                        AND id > _id;
                IF @id IS NOT NULL OR _parent = @start_with THEN
                        SET @level = @level + 1;
                        RETURN @id;
                END IF;
                SET @level := @level - 1;
                SELECT  id, parent
                INTO    _id, _parent
                FROM    t_hierarchy
                WHERE   id = _parent;
        END LOOP;
END

y utilizar en una consulta como esta:

SELECT  hi.*
FROM    (
        SELECT  hierarchy_connect_by_parent_eq_prior_id(id) AS id, @level AS level
        FROM    (
                SELECT  @start_with := 0,
                        @id := @start_with,
                        @level := 0
                ) vars, t_hierarchy
        WHERE   @id IS NOT NULL
        ) ho
JOIN    t_hierarchy hi
ON      hi.id = ho.id

Este es, por supuesto, MySQL específica, pero es muy rápido.

Si queremos que esto sea portable entre PostgreSQL y MySQL, usted puede utilizar PostgreSQL's contrib para CONNECT BY y el abrigo de la consulta en un procedimiento almacenado con el mismo nombre para ambos sistemas.

Me acabo de hacer esto por mí mismo, en realidad! He utilizado el modelo de conjunto anidado de representación de datos jerárquicos en una base de datos relacional.

Gestión de datos jerárquicos en MySQL era de oro puro para mí . conjuntos anidados son el segundo modelo descrito en dicho artículo.

Hay que elegir entre los modelos de la serie anidada de adyacencia y. El artículo Gestión de datos jerárquicos en MySQL hace que para una buena introducción.

Para una discusión teórica, ver árboles de Celko y jerarquías .

Es bastante fácil de implementar una lista de rosca si su base de datos compatible con las funciones de ventanas. Todo lo que necesita es una referencia recursiva en la tabla de base de datos destino, como por ejemplo:

create Tablename (
  RecordID integer not null default 0 auto_increment,
  ParentID integer default null references RecordID,
  ...
)

A continuación, puede utilizar una expresión de tabla común recursiva para mostrar una vista en cadena. Un ejemplo está disponible aquí .

En realidad, tiene que haber un equilibrio entre lectura y escritura.

Si estás bien con la actualización de un montón de filas en cada inserción, a continuación, conjunto anidado (o un equivalente) le dan fácil, rápido lee.

Aparte de eso, una FK simple en la matriz te dará inserción ultra-simple, pero bien podría ser una pesadilla para su recuperación.

Creo que me gustaría ir con los conjuntos anidados, pero tener cuidado con los patrones de volumen de datos y de utilización esperados (actualizar varios, tal vez muchos, filas de dos columnas indizadas (para Información de izquierda y derecha) para cada inserto podría ser un problema en algún momento).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top