Domanda

In precedenza, avevo posto la domanda .

Il problema è che le esigenze della nostra struttura di file sono molto elevate.

Ad esempio, stiamo cercando di creare un contenitore con un massimo di 4500 file e dati da 500mb.

La struttura del file di questo contenitore è costituita da

  • DB SQLite (meno di 1 MB)
  • File di tipo XML basato su testo
  • Immagini all'interno di una struttura di cartelle dinamica che costituisce il resto dei 4.500 file

  • Dopo la creazione iniziale, i file di immagini vengono letti solo ad eccezione dell'eliminazione.

  • Il piccolo db viene utilizzato regolarmente quando si accede al contenitore.

Tar, Zip e simili sono troppo lenti (anche con compressione 0). Lo so è soggettivo, lo so, ma per decomprimere un contenitore di queste dimensioni è più di 20 secondi.

Qualche idea?

È stato utile?

Soluzione

Tre cose.

1) Ciò che Timothy Walters ha detto è giusto, entrerò nei dettagli.

2) 4500 file e 500 Mb di dati sono semplicemente molti dati e scritture su disco. Se stai operando sull'intero set di dati, sarà lento. Solo verità I / O.

3) Come altri hanno già detto, non ci sono dettagli sul caso d'uso.

Se ipotizziamo uno scenario di accesso casuale di sola lettura, allora quello che dice Timothy è praticamente morto e l'implementazione è semplice.

In poche parole, ecco cosa fai.

Concatenate tutti i file in un singolo BLOB. Durante la concatenazione, si tiene traccia del loro nome file, della lunghezza del file e dell'offset che il file inizia all'interno del BLOB. Scrivi tali informazioni in un blocco di dati, ordinati per nome. Chiameremo questo Sommario o blocco TOC.

Quindi, concatenate i due file insieme. Nel caso semplice, è necessario prima il blocco TOC, quindi il blocco dati.

Quando si desidera ottenere dati da questo formato, cercare il sommario per il nome del file, afferrare l'offset dall'inizio del blocco dati, aggiungere la dimensione del blocco sommario e leggere FILE_LENGTH byte di dati. Semplice.

Se vuoi essere intelligente, puoi mettere il sommario alla fine del file BLOB. Quindi, aggiungere alla fine, l'offset all'inizio del sommario. Quindi cerchi la fine del file, esegui il backup di 4 o 8 byte (a seconda della dimensione del tuo numero), prendi QUESTO valore e cerchi ancora più indietro all'inizio del tuo sommario. Quindi sei tornato al punto di partenza. Lo fai in modo da non dover ricostruire l'archivio due volte all'inizio.

Se disponi il tuo sommario in blocchi (diciamo 1K byte di dimensione), puoi facilmente eseguire una ricerca binaria sul sommario. Basta riempire ogni blocco con le voci delle informazioni sul file e quando si esaurisce la stanza, scrivere un marker, pad con zero e passare al blocco successivo. Per eseguire la ricerca binaria, conosci già le dimensioni del sommario, inizia nel mezzo, leggi il primo nome del file e vai da lì. Presto troverai il blocco, quindi leggerai il blocco e lo scansionerai per il file. Questo lo rende efficiente per la lettura senza avere l'intero sommario nella RAM. L'altro vantaggio è che il blocco richiede meno attività del disco rispetto a uno schema incatenato come TAR (in cui è necessario eseguire la scansione dell'archivio per trovare qualcosa).

Ti suggerisco di riempire i file per bloccare anche le dimensioni, i dischi come funzionano con blocchi di dati di dimensioni normali, neanche questo è difficile.

Aggiornare questo senza ricostruire l'intera cosa è difficile. Se desideri un sistema contenitore aggiornabile, puoi anche consultare alcuni dei progetti di file system più semplici, perché è quello che stai davvero cercando in quel caso.

Per quanto riguarda la portabilità, ti suggerisco di memorizzare i tuoi numeri binari nell'ordine di rete, poiché la maggior parte delle librerie standard hanno routine per gestire quei dettagli per te.

Altri suggerimenti

Mentre sembra che tu stia facendo operazioni arbitrarie sul file system sul tuo contenitore (diciamo, creazione, cancellazione di nuovi file nel contenitore, sovrascrittura di file esistenti, aggiunta), penso che dovresti optare per un qualche tipo di file system. Allocare un file di grandi dimensioni, quindi creare una struttura di file system al suo interno.

Sono disponibili diverse opzioni per il file system: sia per Berkeley UFS che per Linux ext2 / ext3, sono disponibili librerie in modalità utente. Potrebbe anche essere possibile trovare un'implementazione FAT da qualche parte. Assicurati di comprendere la struttura del file system e scegline uno che consenta l'estensione. So che ext2 è abbastanza facile da estendere (da un altro gruppo di blocchi) e FAT è difficile da estendere (è necessario accodarlo al FAT).

In alternativa, puoi inserire un formato di disco virtuale ancora al di sotto del file system, consentendo la rimappatura arbitraria dei blocchi. Quindi " gratuito " i blocchi del file system non devono necessariamente apparire sul disco e puoi allocare il disco virtuale molto più grande di quanto sarà il file contenitore reale.

Lavorando sul presupposto che avrai solo bisogno dell'accesso in sola lettura ai file perché non semplicemente unirli tutti insieme e avere un secondo "indice" file (o un indice nell'intestazione) che indica il nome del file, la posizione iniziale e la lunghezza. Tutto quello che devi fare è cercare il punto iniziale e leggere il numero corretto di byte. Il metodo varierà a seconda della lingua ma è abbastanza semplice nella maggior parte di essi.

La parte più difficile diventa quindi la creazione del tuo file di dati + indice, e anche questo è piuttosto semplice!

Un'immagine del disco ISO potrebbe fare il trucco. Dovrebbe essere in grado di contenere facilmente molti file ed è supportato da molti software su tutti i principali sistemi operativi.

Innanzitutto, grazie per aver ampliato la tua domanda, aiuta molto a fornire risposte migliori.

Dato che avrai comunque bisogno di un database SQLite, hai visto le prestazioni di metterlo tutto nel database? La mia esperienza si basa su SQL Server 2000/2005/2008, quindi non sono positivo delle capacità di SQLite ma sono sicuro che sarà un'opzione abbastanza veloce per cercare record e ottenere i dati, pur consentendo comunque l'eliminazione e / o opzioni di aggiornamento.

Di solito non consiglierei di mettere i file nel database, ma dato che la dimensione totale di tutte le immagini è di circa 500 MB per 4500 immagini, stai guardando un po 'più di 100K per immagine, giusto? Se stai utilizzando un percorso dinamico per memorizzare le immagini, allora in un database leggermente più normalizzato potresti avere un "ImagePaths" tabella che mappa ogni percorso su un ID, quindi è possibile cercare immagini con quel PathID e caricare i dati dalla colonna BLOB secondo necessità.

I file XML potrebbero anche trovarsi nel database SQLite, il che fornisce un singolo "file di dati" per la tua app che può spostarsi tra Windows e OSX senza problemi. Puoi semplicemente fare affidamento sul tuo motore SQLite per fornire le prestazioni e la compatibilità di cui hai bisogno.

Il modo in cui lo ottimizzi dipende dal tuo utilizzo, ad esempio se hai spesso bisogno di ottenere tutte le immagini in un determinato percorso, avere un PathID (come numero intero per le prestazioni) sarebbe veloce, ma se stai mostrando tutto immagini che iniziano con " A " e mostra semplicemente il percorso come proprietà, quindi un indice sulla colonna ImageName sarebbe più utile.

Sono un po 'preoccupato, tuttavia, che suona come un'ottimizzazione prematura, poiché è davvero necessario trovare una soluzione che funzioni' abbastanza velocemente ', astrarre la meccanica di essa in modo che la tua applicazione (o entrambe le app se hai sia Mac che PC versioni) utilizzano un repository semplice o simile e quindi è possibile modificare il metodo di archiviazione / recupero a piacimento senza implicazioni per l'applicazione.

Controlla Solid File System - sembra essere ciò di cui hai bisogno.

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