2011-10-21 17 views
8

Ho un file csv di 215 MB che ho analizzato e archiviato nei dati del core avvolto nei miei oggetti personalizzati. Il problema è che il mio file sqlite di dati di base è di circa 260 MB. Il file CSV contiene circa 4,5 milioni di righe di dati sul sistema di trasporto della mia città (fermata dell'autobus, orari, percorsi, ecc.).Come ridurre o comprimere le dimensioni del file sqlite di Core Data?

Ho provato a modificare gli attributi in modo che gli array di stringhe che rappresentano i tempi di arresto siano memorizzati invece come file NSData, ma per qualche motivo la dimensione del file rimane ancora a circa 260 MB.

Non riesco a spedire un'app di queste dimensioni. Dubito che qualcuno vorrebbe scaricare un'applicazione da 260MB anche se ciò significa che hanno l'intero programma di transito della città su di esso.

Esistono modi per comprimere o ridurre a icona lo spazio di archiviazione utilizzato (anche se ciò significa non utilizzare i dati principali, sono disposto a ricevere suggerimenti)?

MODIFICA: Voglio solo fornire un aggiornamento in questo momento perché ho fissato le dimensioni del file incredulo. Con una manipolazione intelligente che coinvolge le stringhe, l'indicizzazione e la normalizzazione del database in generale, sono riuscito a ridurre le dimensioni fino a 6,5 ​​MB o 2,6 MB quando compresso. Circa 105.000 oggetti archiviati in Core Data contenenti tutti i dettagli del sistema di trasporto della città. Sono quasi in lacrime adesso D ':

+0

Ho appena visto il tuo commento aggiornato sulla dimensione finale. Molto impressionante. La compressione 100: 1 dei dati del mondo reale dovrebbe rendere orgoglioso chiunque. –

+0

Molto tardi ma se controlli l'app Transit, ho parlato con loro e sono riusciti a ottenere 260 MB in soli ** 800 KB ** – Milo

risposta

0

Potrebbe essere possibile eseguire la normalizzazione del database.

Cercare tutto ciò che potrebbe essere ridondante o gli stessi valori memorizzati in più righe. Probabilmente avrai bisogno di ristrutturare il tuo database in modo che questi valori duplicati (se presenti) siano memorizzati in tabelle separate e quindi referenziati dalla loro riga originale per mezzo di id.

0

Quanto è grande il file sqlite compresso? Se è abbastanza piccolo, la cosa più semplice sarebbe spedirla compressa, quindi decomprimerla in NSCachesDirectory.

+0

Per "compresso" intendevo compresso con gzip, btw. –

+0

Il file è 57.7 MB quando gzip. Potresti essere su qualcosa qui. La mia unica preoccupazione ora è quanto tempo normalmente impiegherebbe il telefono per decomprimerlo. –

8

A meno che il tuo CSV originale non sia codificato in modo veramente sciocco, sembra improbabile che la dimensione non scenda al di sotto dei 100 M, indipendentemente dalla quantità di compressione. Questo è ancora molto grande per un'app. La soluzione è spostare i tuoi dati su un servizio web. Si consiglia di scaricare e memorizzare in cache parti significative, ma se si parla di milioni di record, il recupero da un server sembra il migliore. Inoltre, devo credere che di tanto in tanto il sistema di transito cambia, e sarebbe frustrante dover aggiornare un'app da molti-10-di-MB ogni volta che ci fosse un unico aggiustamento di stop.


Ho detto che, ma in realtà ci sono alcune cose che si può prendere in considerazione:

  • Spostare booleani in un campi di bit. Puoi mettere 64 booleani in un NSUInteger. (E non usare un intero intero a 64 bit se hai solo bisogno di 8 bit. Memorizza la cosa più piccola che puoi.)
  • Comprimi come memorizzare i tempi. Ci sono solo 1440 minuti in un giorno. Puoi memorizzarlo in 2 byte. I tempi di transito non sono generalmente al secondo; non hanno bisogno di un CGFloat.
  • I giorni della settimana e le date possono essere compressi allo stesso modo.
  • Ovviamente è necessario normalizzare qualsiasi stringa. Guarda il CSV per i valori di stringa duplicati su molte linee.
  • Generalmente raccomanderei sqlite raw anziché dati core per questo tipo di problema. I dati principali riguardano più la persistenza degli oggetti rispetto all'archiviazione dei dati grezzi. Il fatto che tu stia vedendo un aumento del 20% rispetto al CSV (che non è di per sé molto efficiente) non è una buona direzione per questo problema.
  • Se si desidera ottenere ancora più stretto e non sono necessarie funzionalità di ricerca ottimali, è possibile creare blob di dati compressi. Lo facevo sugli interruttori del telefono dove la memoria era estremamente stretta. Si crea una struttura di bit field e si assegnano 5 bit per una variabile, e 7 bit per un'altra, ecc. Con questo, e un po 'di tempo per mescolare le cose in modo che si allineino correttamente sui confini delle parole, si può ottenere abbastanza stretto.

Dal momento che ti interessano di più del tuo dimensione iniziale download e possono essere disposti a espandere i propri dati più tardi per un accesso più veloce, si può considerare la compressione domain-specific molto. Ad esempio, nella discussione precedente, ho menzionato come arrivare a 2 byte per volta. In molti casi potresti probabilmente scendere a 1 byte memorizzando i tempi come minuti delta dall'ultima volta (poiché la maggior parte dei tuoi tempi aumenterà sempre di piccoli passi se sono orari di bus e treni). Abbandonando il database, è possibile creare un file di dati molto strettamente codificato che è possibile estrarre in un database al primo avvio.

È inoltre possibile utilizzare la conoscenza specifica del dominio per codificare le stringhe in token più piccoli. Se codificassi il sistema della metropolitana di New York, noterei che alcune stringhe appaiono molto, come "Avenue", "Road", "Street", "East", ecc. Probabilmente le codificherei come ASCII non stampabili come^A,^R,^S,^E, ecc. Probabilmente codificherei "138 Street" come due byte (0x8A13). Questo naturalmente è basato sulla mia conoscenza che è (0x8a) non si presenta mai nelle fermate della metropolitana di New York. Non è una soluzione generale (a Parigi potrebbe essere un problema), ma può essere utilizzata per comprimere altamente i dati di cui hai una conoscenza speciale. In una città come Washington DC, credo che la loro via più numerata sia la 38a Strada, e poi c'è una direzione a 4 valori. Quindi puoi codificarlo in due byte, prima un token "numerato" e poi un campo bit con 2 bit per il quadrante e 6 bit per il numero civico. Questo tipo di pensiero può potenzialmente ridurre in modo significativo le dimensioni dei dati.

+0

Sono assolutamente d'accordo con te qui. Tuttavia, l'app è pensata per essere in grado di operare offline, il che significa che devono essere inclusi tutti i dati. Altrimenti, questo mi era effettivamente passato per la testa e sarebbe stato l'ideale. –

+0

Sì; Stavo pensando molto di più su come memorizzare meglio il CSV. Penso ci siano molte opzioni. CSV in realtà non è così efficiente. Penso che qualsiasi cosa tu possa ottenere da gzip tu possa migliorare con soluzioni di storage più intelligenti. –

+0

Grazie Rob per la tua risposta riflessiva. Ho consultato il database e ho notato che molte informazioni sono state ripetute, in particolare gli indicatori di direzione, che sono memorizzati come stringhe. Passando al codice ora per eliminarlo. Mi piace il tuo suggerimento del delta time e darò uno scatto. Spero di riuscire a portare questa bestia sotto i 200MB e poi gzip ed estrarla nella cartella delle cache al primo avvio. –

Problemi correlati