Boas visões gerais
De um modo geral, você está tomando uma decisão entre tempos de leitura rápidos (por exemplo, conjunto aninhado) ou tempos de gravação rápidos (lista de adjacências). Geralmente, você acaba com uma combinação das opções abaixo que melhor atendem às suas necessidades. A seguir, é apresentada uma leitura aprofundada:
- Mais uma comparação de intervalos aninhados vs. lista de adjacências : a melhor comparação que encontrei da lista de adjacências, caminho materializado, conjunto aninhado e intervalo aninhado.
- Modelos para dados hierárquicos : slides com boas explicações sobre tradeoffs e exemplos de uso
- Representando hierarquias no MySQL : visão geral muito boa do Nested Set em particular
- Dados hierárquicos em RDBMSs : conjunto de links mais abrangente e bem organizado que eu já vi, mas não muito na explicação
Opções
Conheço e tenho características gerais:
- Lista de adjacências :
- Colunas: ID, ParentID
- Fácil de implementar.
- O nó barato move, insere e exclui.
- Caro para encontrar o nível, ascendência e descendentes, caminho
- Evite N + 1 por meio de expressões de tabela comuns em bancos de dados que os suportam
- Conjunto aninhado (também conhecido como Traversal de árvore de pré-encomenda modificada )
- Colunas: Esquerda, Direita
- Ascendência barata, descendentes
O(n/2)
Movimentos, inserções e exclusões muito caros devido à codificação volátil
- Tabela de ponte (também conhecida como tabela de fechamento / gatilhos w )
- Usa tabela de junção separada com: ancestral, descendente, profundidade (opcional)
- Ascendência e descendentes baratos
- Escreve custos
O(log n)
(tamanho da subárvore) para inserção, atualizações e exclusões - Codificação normalizada: boa para estatísticas RDBMS e planejador de consultas em junções
- Requer várias linhas por nó
- Coluna de linhagem (também conhecida como caminho materializado , enumeração de caminho)
- Coluna: linhagem (por exemplo, / pai / filho / neto / etc ...)
- Descendentes baratos via consulta de prefixo (por exemplo
LEFT(lineage, #) = '/enumerated/path'
) - Escreve custos
O(log n)
(tamanho da subárvore) para inserção, atualizações e exclusões - Não relacional: depende do tipo de dados Array ou formato de seqüência de caracteres serializada
- Intervalos aninhados
- Como o conjunto aninhado, mas com real / float / decimal para que a codificação não seja volátil (movimentação / inserção / exclusão de baixo custo)
- Tem problemas reais / de flutuação / representação decimal / precisão
- A variante de codificação da matriz adiciona a codificação ancestral (caminho materializado) para "livre", mas com a dificuldade adicional da álgebra linear.
- Mesa plana
- Uma lista de adjacências modificada que adiciona uma coluna de nível e classificação (por exemplo, pedido) a cada registro.
- Barato para iterar / paginar
- Movimentação e exclusão caras
- Bom uso: discussão por tópicos - fóruns / comentários do blog
- Várias colunas de linhagem
- Colunas: uma para cada nível de linhagem, refere-se a todos os pais até a raiz, os níveis inferiores ao nível do item são definidos como NULL
- Ancestrais baratos, descendentes, nível
- Inserção barata, excluir, mover as folhas
- Inserção cara, exclusão, movimentação dos nós internos
- Limite rígido para a profundidade da hierarquia
Notas específicas do banco de dados
MySQL
Oráculo
- Use CONNECT BY para percorrer as Listas de Adjacência
PostgreSQL
- tipo de dados ltree para caminho materializado
servidor SQL
- Resumo geral
- O ano de 2008 oferece que o tipo de dados HierarchyId parece ajudar na abordagem da coluna Lineage e expandir a profundidade que pode ser representada.
Closure Tables
são superiores aAdjacency List
,Path Enumeration
eNested Sets
em termos de facilidade de uso (e eu estou supondo que o desempenho também).