14

Ho un set di dati gerarchici utilizzati in un database SQL Server. I dati sono memorizzati con un guid come chiave primaria e una parentGuid come una chiave esterna che punta agli oggetti parent immediati. Accedo i dati più spesso tramite Entity Framework in un progetto WebApi. Per rendere la situazione un po 'più complessa, devo anche gestire i permessi basati su questa gerarchia in modo tale che un'autorizzazione applicata a un genitore si applichi a tutti i suoi discendenti. La mia domanda è questa:Dati SQL gerarchici (tabella CTE ricorsiva vs gerarchico o tabella di chiusura)

Ho cercato dappertutto e non posso decidere quale sia la soluzione migliore per gestire questa situazione. So di avere le seguenti opzioni.

  1. Posso creare Recursive CTEs, Common Table Expression, (aka RCTE) per gestire i dati gerarchici. Questo sembra essere l'approccio più semplice per l'accesso normale, ma sono preoccupato che potrebbe essere lento quando viene utilizzato per determinare i livelli di autorizzazione per gli oggetti figlio.
  2. Posso creare un campo di tipo dati hierarchyId nella tabella e utilizzare funzioni fornite da SQL Server come GetAncestor(), IsDescendantOf() e così via. Sembra che renderebbe l'interrogazione abbastanza semplice, ma sembra richiedere un trigger di inserimento/aggiornamento piuttosto complesso per mantenere corretto il campo della gerarchia ID tramite inserimenti e spostamenti
  3. Posso creare uno closure table, che memorizzerebbe tutte le relazioni nella tabella. Lo immagino come tale: colonna genitore e colonna figlio, ogni genitore -> relazione figlio sarebbe rappresentata. (cioè 1-> 2 2-> 3 sarebbe rappresentato nel database come 1-2, 1-3, 2-3). Lo svantaggio è che questo richiede l'inserimento, l'aggiornamento e l'eliminazione dei trigger anche se sono abbastanza semplici e questo metodo genera molti record.

Ho provato a cercare dappertutto e non riesco a trovare nulla che dia qualche consiglio tra questi tre metodi.

PS io sono aperto anche ad eventuali soluzioni alternative a questo problema

+0

Contrassegnare la domanda con la versione di SQL Server che si sta utilizzando. Le tue domande tendono a passare dal bambino al genitore o viceversa? Un RCTE che cammina sull'albero seguendo i link padre per un singolo figlio non dovrebbe essere troppo cattivo. Andare dall'altra parte per tutti i bambini è dove rallenta. – HABO

+0

Non riesco a controllare la versione ora, ma lo farò in seguito. Penso che sia il 2008 o il più recente. È probabile che diventi più spesso genitori di figli che genitori di bambini – jp36

+0

Non riesco ad aggiungere un altro tag, ma è SQL Server 2008 r2. – jp36

risposta

9

ho usato tutti e tre i metodi. È principalmente una questione di gusti.

Sono d'accordo che la gerarchia con le relazioni genitore-figlio nella tabella sia la più semplice. Lo spostamento di un sottoalbero è semplice ed è facile codificare l'accesso ricorsivo con le CTE. Le prestazioni saranno un problema solo se si dispone di strutture ad albero molto grandi e si accede frequentemente ai dati gerarchici. Per la maggior parte, le CTE ricorsive sono molto veloci quando si hanno gli indici corretti sul tavolo.

Il tavolo di chiusura è più simile a un supplemento a quanto sopra. Trovare tutti i discendenti di un dato nodo è velocissimo, non hai bisogno dei CTE, solo un altro extra, quindi è dolce. Sì, il numero di record scoppia, ma penso che non sia più di N-1 volte il numero di nodi per un albero di profondità N (ad esempio un albero terziario di profondità 5 richiederebbe 1 + 3 + 9 + 27 + 81 = 121 connessioni quando si memorizza solo la relazione genitore-figlio contro 1 + 3 + (9 * 2) + (27 * 3) + (81 * 4) = 427 per la tabella di chiusura). Inoltre, i record delle tabelle di chiusura sono così ristretti (solo 2 pollici al minimo) che occupano quasi nessuno spazio. La generazione dell'elenco di record da inserire nella tabella di chiusura quando un nuovo record viene inserito nella gerarchia richiede un po 'di overhead.

Personalmente mi piace HierarchyId dato che combina davvero il vantaggio dei due precedenti, che è memoria compatta e accesso fulmineo. Una volta impostato, è facile interrogare e occupa pochissimo spazio. Come hai detto, è un po 'difficile spostare i sottoalberi, ma è gestibile. Comunque, quanto spesso muovi davvero una sottostruttura in una gerarchia? Ci sono alcuni link che puoi trovare che suggeriscono alcuni metodi, ad es.:

http://sqlblogcasts.com/blogs/simons/archive/2008/03/31/SQL-Server-2008---HierarchyId---How-do-you-move-nodes-subtrees-around.aspx

Il principale svantaggio che ho trovato per hierarchyid è la curva di apprendimento. Non è così ovvio come lavorare con esso come gli altri due metodi. Ho collaborato con alcuni sviluppatori SQL molto brillanti che si sono spesso impigliati su di esso, quindi si finisce con uno o due esperti residenti che devono mettere in campo domande da tutti gli altri.

+3

Due inconvenienti che ho riscontrato durante la mia incursione iniziale in gerarchia Ide era, in primo luogo, la gestione degli inserimenti/aggiornamenti in blocco nel trigger di inserimento/aggiornamento e, in secondo luogo, l'utilizzo della tabella gerarchia in C# tramite Entity Framework. Avete qualche consiglio o informazioni sulla gestione di uno di questi? Inoltre, questa risposta è stata molto utile, ma aspetterò un po 'prima di selezionarla per incoraggiare chiunque altro possa avere informazioni utili. – jp36

+0

C'è un altro svantaggio che si incontra quando si tenta di utilizzare questi tipi di relazioni in Analysis Services indipendentemente dal metodo scelto per rappresentarli. Self-join, loops e hierarchyid non sono supportati in Analysis Services, il che significa che si finisce per dover eseguire uno di due soluzioni alternative; (1) creare viste di appiattimento per rappresentare le dimensioni memorizzate in questo modo, oppure (2) utilizzare SSIS per appiattire le dimensioni in un database BI (schema stella o fiocco di neve). Una soluzione alternativa richiede manutenzione ogni volta che viene aggiunto un nuovo elemento alla gerarchia. – JamieSee