2012-05-30 16 views
16

Ho un file csv da 7,4 Gb. Dopo averlo convertito in un database sqlite con un python script, il DB di output è 4,7 Gb, circa il 60% della dimensione originale.sqlite3 comprime i dati?

Il csv ha circa 150.000.000 di righe. Ha intestazione:

tkey,ipaddr,healthtime,numconnections,policystatus,activityflag 

e ogni riga simile a

261846,172.10.28.15,2012-02-03 16:15:00,22,1,1 

Lo script healthtime usa per suddividere i dati in tabelle 192 tabelle

Quando ho visto questi numeri, ho pensato io aveva commesso un errore da qualche parte. Quanto è grande una riduzione delle dimensioni del file dovrei aspettarmi dall'efficienza aggiunta di scrivere solo l'ora di integrità 192 volte anziché 150.000.000 di volte?

MODIFICA: Non appena ho postato questo ho capito la risposta. Sto rimuovendo circa il 40% della stringa, quindi la riduzione del 40% delle dimensioni.

Edit 2 Calcoliamo la differenza di dimensioni tra il testo in chiaro:

"261846,172.10.28.15,2012-02-03 16:15:00,22,1,1" 

E la voce di base di dati:

db(261846,'172.10.28.15',22,1,1) 

Prima di tutto, facciamo cadere da 46 a 26 caratteri nella rappresentazione del testo normale.

I caratteri rimanenti sono:

"261846,172.10.28.15,22,1,1" 

o 26 byte. Se ogni intero deve essere memorizzato in 32 bit (4 byte), allora abbiamo:

12 byte (ipaddr) + 4 byte * 4 (campi interi) = 28 byte.

Quindi sembra che la conversione in numeri interi renda l'archiviazione leggermente meno efficiente e tutti i miei guadagni derivino dalla riduzione del numero di caratteri memorizzati in ogni riga.

+6

Ovviamente sqlite è un formato binario, mentre csv è testo. La differenza di dimensione del 60% può essere causata da questo. –

+1

Mi spiace, qual è lo stato di salute? Una rapida ricerca su google non ha rivelato nulla. –

+0

healthtime è solo il nome del campo. – Maus

risposta

23

SQLite non sta eseguendo un algoritmo di compressione, ma memorizzerà i dati in un file binario anziché in un file di testo. Ciò significa che i dati possono essere memorizzati in modo più efficiente, ad esempio utilizzando un numero a 32 bit (4 byte) per rappresentare 10,000,000 invece di memorizzarlo come 8 byte di testo (o più se il file è unicode).

Qui ci sono ulteriori dettagli sul SQL Database File Format se siete interessati.

Ha senso?

+4

Vale la pena sottolineare che SQLite utilizza solo il numero di byte necessario. Ad esempio il valore 7 richiede solo un byte. –

+2

Il valore 7 ha bisogno di due byte: un tipo seriale varint che in questo caso sarebbe lungo un byte e il valore che sarebbe un byte in questo caso. Il tipo seriale è presente per ogni valore nel database, è un byte per valori nulli e numeri ed è una lunghezza variabile fino a 9 byte per blob e testo. Ad esempio, un intero lungo 32 bit richiede 5 byte, un float a 64 bit è 9 byte poiché in entrambi i casi ha un tipo seriale di un byte. – thomasrutter

17

SQLite, per impostazione predefinita, non comprime i dati scritti sul disco; tuttavia, SQLite ha una serie di "Estensioni proprietarie" per questo e altri scopi. Cerca ZIPVFS nei collegamenti come segue.

http://www.sqlite.org/support.html e http://www.hwaci.com/sw/sqlite/prosupport.html

È possibile ottenere un sacco di "compressione" nei dati codificando campi come numeri interi. Ad esempio, un indirizzo IP è stato progettato per adattarsi a una parola (4 byte).Ogni ottetto dell'indirizzo può essere rappresentato in un byte di una parola.

string[] octets = '172.168.0.1'.split('.') 
int ip = atoi(octets[0]) << 24 
ip |= atoi(octets[1]) << 16 
ip |= atoi(octets[2]) << 8 
ip |= atoi(octets[3]) 

Inoltre, il timestamp può essere rappresentato in tempo Unix, che è il numero di secondi dall'epoca.

UPDATE mytable SET healthtime = CAST(strftime('%s',healthtime) AS INTEGER); 

See the Date and Time functions

Nota la direttiva CAST nella SQL sopra: SQLite non rispettare tipo su una colonna, così si può avere un gruppo di cifre memorizzate come una stringa; aumentando le dimensioni del campo più del necessario (questo farà sì che alcune query si comportino in modo strano).

Un'altra cosa: la dimensione del campo non è l'unica parte della storia. Ricorda che anche gli indici occupano uno spazio e gli indici sugli interi sono più efficienti, in termini di dimensioni e prestazioni del disco.