Domanda

Questo è un follow-up a:
MySQL - E 'possibile ottenere tutti sub-elementi in una gerarchia?

Ho un arbitrario approfondita adiacenza Lista modello tabella (io sono al punto che possono convertirlo in un modello nidificato set .

Ho letto i dati di MySQL su come utilizzare un modello di set nidificato, anche se sembrava avere sempre più complessa e molto complessa da fare funzioni di base come l'inserimento, l'aggiornamento e la cancellazione.

Un altro blog che mostra come utilizzare un sistema di trigger con il modello di lista di adiacenza di tenere una tabella di antenati che si riferisce ciascun oggetto ai suoi antenati.


In questo momento ho bisogno di essere in grado di restituire un elenco di tutti i figli di un dato nodo, modificare o cancellarli. Questa struttura gerarchica non cambierà per tutto il tempo, una volta creato, ma ci sarà una quantità di massa di strutture gerarchiche.

I tre metodi che vedo sono:

  1. Creato una stored procedure , che avrebbe fatto una query ricorsive che restituisce a tutti i bambini.

  2. Converti in Nested Set Modello che richiederebbe di entrare in complessità e, eventualmente, creare una stored procedure per aggiungere, modificare ed eliminare in questo.

  3. creare la tabella Antenato sopra descritti su inserto / trigger DELETE per gestire tutti i dati.

Se non ci sono altri metodi non sto esplorando, per favore fatemelo sapere e io aggiornare questa lista.

È stato utile?

Soluzione

Quassnoi ha eseguito alcuni test di performance sul set del modello nidificato e il modello di lista di adiacenza e documentato i risultati e le raccomandazioni il suo post sul blog adiacenza lista vs. set nidificati: MySQL . La sintesi è:

  • set nidificati è più veloce per andare a prendere tutti i nodi secondari o tutti i nodi genitore.
  • set annidata è una cattiva idea se avete spesso bisogno di aggiornare la tabella.

Ecco la conclusione dal suo articolo:

  

In MySQL, il modello nested sets dovrebbe essere preferito se gli aggiornamenti alla struttura hierarhical sono infrequenti ed è conveniente per bloccare la tabella per la durata di un aggiornamento (che può richiedere minuti su un lungo tavolo).

     

Questo implica creare la tabella utilizzando motore di archiviazione MyISAM, creando il riquadro di selezione di un tipo di geometria come descritto sopra, indicizzazione con un indice spaziale e persistente il livello nella tabella.

     

Se gli aggiornamenti alla tabella sono frequenti o è inaffordable per bloccare il tavolo per un lungo periodo di tempo implicita da un aggiornamento, allora il modello lista di adiacenza deve essere utilizzato per memorizzare i dati gerarchici.

     

Ciò richiede la creazione di una funzione per interrogare la tabella.

Il resto degli spettacoli articolo come definire il tavolo, implementare le query e dà misurazioni delle prestazioni. L'utilizzo dell'indice spaziale è un'idea intelligente per migliorare le prestazioni del modello set nidificato che potrebbe essere una novità per voi.


Se state considerando anche gli approcci senza MySQL allora si potrebbe desiderare di guardare PostgreSQL che è un altro libero e database open-source. PostgreSQL supporta le query ricorsive in forma di ricorsiva espressioni di tabella comuni che rendono l'interrogazione di dati gerarchiche più facile che in MySQL e anche dare prestazioni migliori. Quassnoi ha anche scritto un articolo adiacenza lista vs. annidata set: PostgreSQL che mostra i dettagli

.

Mentre stiamo parlando, cercando in altri approcci, il database di Oracle è anche una menzione merita. Oracle ha anche una CONNECT BY un'estensione personalizzata che rendono interrogazione dei dati gerarchica molto facile e veloce. articolo adiacenza lista di Quassnoi vs set nidificati: Oracle di nuovo copre i dettagli delle prestazioni. La query è necessario per ottenere tutti i bambini è estremamente semplice, in questo caso:

SELECT *
FROM yourtable
START WITH id = 42
CONNECT BY parent = PRIOR id

Altri suggerimenti

vorrei sempre andare con il nidificati Set per la semplicità di taglio e convienience. Suggerisco sempre questo articolo . Essa mostra eccellente le query che sono necessarie per il lavoro con tali dati hierachrchical. L'unico svantaggio che vedo qui è che si può ottenere più lento con l'inserimento / updateing nuovi record quando il hierachry raggiunto un certo livello di complessità, ma la lettura è più veloce rispetto a molte altre soluzioni che hae visto.

Solo per darvi un esempio l'articolo di cui sopra:

SELECT t1.name AS lev1, t2.name as lev2, t3.name as lev3, t4.name as lev4
FROM category AS t1
LEFT JOIN category AS t2 ON t2.parent = t1.category_id
LEFT JOIN category AS t3 ON t3.parent = t2.category_id
LEFT JOIN category AS t4 ON t4.parent = t3.category_id
WHERE t1.name = 'ELECTRONICS';

+-------------+----------------------+--------------+-------+
| lev1        | lev2                 | lev3         | lev4  |
+-------------+----------------------+--------------+-------+
| ELECTRONICS | TELEVISIONS          | TUBE         | NULL  |
| ELECTRONICS | TELEVISIONS          | LCD          | NULL  |
| ELECTRONICS | TELEVISIONS          | PLASMA       | NULL  |
| ELECTRONICS | PORTABLE ELECTRONICS | MP3 PLAYERS  | FLASH |
| ELECTRONICS | PORTABLE ELECTRONICS | CD PLAYERS   | NULL  |
| ELECTRONICS | PORTABLE ELECTRONICS | 2 WAY RADIOS | NULL  |
+-------------+----------------------+--------------+-------+
6 rows in set (0.00 sec)

SQL saggio, non credo che possa ottenere qualsiasi più bella e più semplice;)

Non ho idea di stored procedure modo. Ma dal momento che involces ricorsione (nel tuo caso), non so se sarà veloce con molti livelli della gerarchia. Presumo si può fare un tentativo.

Forse si dovrebbe considerare l'utilizzo di database document-oriented come MongoDB . Si potrebbe rendere la vita molto più facile.

Quando si tratta di insiemi di dati gerarchici trovo meglio avvicinarsi con il caching in mente. Uno dei principali vantaggi di questo metodo di affrontare questo problema in questo modo è che non richiede di de-normalizzazione dei database in qualcosa che potrebbe essere più difficile da mutare.

Da (memcache, Redis, ecc) le ricerche cumuli di memoria sono molto più veloce di SQL per semplici risoluzioni id -> data, io li uso per memorizzare nella cache un elenco degli ID di bambini diretti per ogni nodo. In questo modo è possibile ottenere prestazioni decenti attraverso un algoritmo ricorsivo per costruire una lista completa per qualsiasi nodo.

Per aggiungere / eliminare un nuovo nodo, si avrà solo bisogno di invalidare la sua diretta della cache genitore O(1).

Se questo non è abbastanza veloce, è possibile aggiungere un altro strato di cache per un elenco di tutti i bambini di un nodo in ogni nodo. In modo che questo lavoro con un set di dati decentemente mutevole, si dovrebbe registrare le prestazioni della cache (rapporto di colpi freschi / cache) di ogni nodo e impostare un livello di tolleranza per quando per memorizzare nella cache. Anche questo può essere memorizzato in un mucchio di memoria dal momento che è dati non vitale.

Se si utilizza questo modello di caching più avanzato, sarà necessario notare questi bambini completi nodo liste dovranno essere invalidate quando da suoi figli sono cambiati O(log n).

Una volta che avete la vostra lista dei figli di id è possibile utilizzare la sintassi WHERE id IN( id1, id2, .... ) di SQL per query per ciò che si vuole.

Una volta ho dovuto memorizzare un disegno di legge-di-materiale complesso sistema gerarchico arbitrario approfondita in un database di SQL-like manager che non era davvero all'altezza del compito, ed è finito per costringere disordinati e difficili indicies, le definizioni dei dati, query, ecc Dopo aver riavviato da zero, usando il gestore db a fornire solo un'API per record di lettura e scrittura su semplici chiavi indicizzati, e facendo tutto il reale ingresso / manipolazione / segnalazione in codice esterno, il risultato finale è stato più veloce da implementare , più facile da capire, e più semplice per mantenere e migliorare. La query più complessa necessaria era essenzialmente SELECT A da B.

Così, invece di incorporare la logica e le operazioni all'interno dei limiti di MySQL, si consideri sbattere fuori il codice per fare quello che vuoi, e basandosi su MySQL solo per il livello più basso ottiene / put.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top