2012-10-27 15 views
17

Sto cercando di implementare un database basato su SQLite in grado di memorizzare l'intera struttura di una cartella da 100 GB con una sottostruttura complessa (in attesa di file 50-100K). L'obiettivo principale del DB sarebbe quello di ottenere query rapide su vari aspetti di questa cartella (dimensione totale, dimensione di qualsiasi cartella, cronologia di una cartella e tutto il suo contenuto, ecc.).Scelta dello schema del database per l'archiviazione del sistema di cartelle

Tuttavia, mi sono reso conto che trovare tutti i file all'interno di una cartella, inclusi tutti è sotto-cartelle non è possibile senza query ricorsive se ho solo fare una tabella di "file" con solo un campo parent_directory. Considero questa come una delle funzionalità più importanti che voglio nel mio codice, quindi ho preso in considerazione due opzioni dello schema per questo come mostrato nella figura seguente.

  1. Nello schema 1, memorizzo tutti i nomi di file in una tabella e i nomi di directory in un'altra tabella. Entrambi hanno un elemento "parentdir", ma hanno anche un campo di testo (apparentemente text/blob sono gli stessi in sqlite) chiamato "FullPath" che salverà l'intero percorso dalla radice al particolare file/directory (come/etc/abc/def/wow/LongPath/test.txt). Non sto assumendo un limite massimo di sottocartelle, quindi questo potrebbe teoricamente essere un campo che consente fino a 30 caratteri K. La mia idea è che se voglio che tutti i file o le directory di un genitore interrogino il fullpath del genitore su questo campo e ottenga i fileID

  2. Nello schema 2, memorizzo solo nomi di file, ID di file e nomi Dir, DirID nelle directory e nelle tabelle dei file, rispettivamente. Ma in una terza tabella chiamata "Ancestors", memorizzo per ogni file un insieme di voci per ogni directory che è il suo antenato (quindi nell'esempio sopra, test.txt avrà 5 voci, che puntano ai DirID delle cartelle ecc, abc, def, wow e longpath rispettivamente). Quindi se voglio il contenuto completo di qualsiasi cartella, cerco il DirID in questa tabella e ottengo tutti i fileID.

posso vedere che nello schema 1 il principale limite potrebbe essere la ricerca full-text della colonna di testo di lunghezza variabile e nello schema 2 il limite principale è che avrei potuto aggiungere una tonnellata di voci per i file che sono sepolto in profondità entro 100 directory o qualcosa del genere.

Quale sarebbe la migliore di queste soluzioni? C'è qualche soluzione migliore a cui non ho pensato?

Two possible schemas to keep rapid allow rapid retrieval of *all* the descendants of a directory in a complex directory structure

+3

Potresti essere interessato a http://dirtsimple.org/2010/11/simplest-way-to-do-tree-based-queries.html –

+0

Wow era esattamente quello che volevo! Quindi la seconda soluzione che ho mostrato è in qualche modo simile a ciò che sta descrivendo, ma descrive anche trigger estremamente eleganti che terrebbero tutti i dati completamente sani senza alcuna sanificazione esterna del codice! Penso che andrò con quel design! – user930916

risposta

17
  1. Il tuo primo schema funzionano bene. Quando si inserisce un indice nella colonna FullPath, utilizzare l'operatore BETWEEN con distinzione tra maiuscole e minuscole per le query oppure utilizzare LIKE con COLLATE NOCASE nell'indice o con PRAGMA case_sensitive_like.

    Si prega di notare che questo schema anche memorizza tutti i genitori, ma gli ID (i nomi) sono tutti concatenati in un unico valore.

    Rinominare una directory richiede l'aggiornamento di tutte le voci della sottostruttura, ma si menziona la cronologia, quindi è possibile che le voci precedenti rimangano invariate.

  2. Il secondo schema è essenzialmente lo Closure Table menzionato nel commento di Dan D. Fare attenzione a non dimenticare le voci per la profondità 0.

    Questo sarà memorizza molti dati, ma essendo ID, i valori non dovrebbero essere troppo grandi.

    (In realtà non c'è bisogno RelationshipID, vero?)

  3. Un'altra scelta per gli alberi memorizzazione è la nested set model, o simile nidificato modello di intervallo. Il modello di serie nidificato consente di recuperare sottostrutture interrogando per un intervallo, ma gli aggiornamenti sono pelosi. Il modello di intervallo nidificato utilizza le frazioni, che non sono un tipo di dati nativo e pertanto non possono essere indicizzate.

Stima che la prima alternativa sarebbe più semplice da usare. Non dovrei essere più lento degli altri se le ricerche sono indicizzate correttamente.

+0

Grazie per la tua descrizione dettagliata sulle 3 idee! In realtà penso che andrò con il Closure Table, che in qualche modo si sente più elegante e come i dati dovrebbero essere realmente nel database (e che il collegamento DirtSimple ha quelli che sembrano trigger molto interessanti che faranno tutta la contabilità sul database stesso, anche se passerò un po 'di tempo a riflettere molto duramente). Anche se l'idea di Abra sembra buona, sono solo un po 'stanco di fare manipolazioni di stringhe e ritengo che l'altra opzione potrebbe essere più interessante. Probabilmente eseguirò alcuni test, anche lo spazio è un limite per me – user930916

+0

E il RelationshipID deve essere aggiunto perché MS Access non mi permette di creare una tabella senza una chiave primaria e ho trovato lo strumento più semplice per creare diagrammi di relazioni :) – user930916

+0

La chiave primaria 'corretta' per quella tabella sarebbe la combinazione di 'DirID' e' FileID'. –

5

Il mio preferito è l'approccio visitation number, che ritengo sarebbe particolarmente utile per te dal momento che rende piuttosto facile eseguire query aggregate su un record e i suoi discendenti.

Problemi correlati