2012-05-30 23 views
16

Tengo un archivo csv de 7.4Gb. Después de convertirlo a una base de datos sqlite con un python script, el DB de salida es 4.7Gb, alrededor del 60% del tamaño original.¿sqlite3 comprime los datos?

El csv tiene alrededor de 150,000,000 filas. Tiene cabecera:

tkey,ipaddr,healthtime,numconnections,policystatus,activityflag 

y cada fila se ve algo como

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

La secuencia de comandos utiliza healthtime para dividir los datos en tablas 192 mesas

Cuando vi por primera vez estos números, asumí que había cometido un error en algún lugar. ¿Qué tan grande de una reducción en el tamaño de archivo debo esperar de la eficacia adicional de solo escribir el tiempo de salud 192 veces en vez de 150,000,000 veces?

EDIT: Tan pronto como publiqué esto me di cuenta de la respuesta. Estoy eliminando aproximadamente el 40% de la cadena, por lo tanto, la reducción del 40% en el tamaño.

Editar 2 Vamos a calcular la diferencia de tamaño entre el texto:

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

Y la entrada de base de datos:

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

En primer lugar, se nos cae de 46 a 26 caracteres en representación de texto sin formato.

Los caracteres restantes son:

"261846,172.10.28.15,22,1,1" 

o 26 bytes. Si cada número entero necesita almacenarse en 32 bits (4 bytes), entonces tenemos:

12 bytes (ipaddr) + 4 bytes * 4 (campos enteros) = 28 bytes.

Parece que la conversión a enteros hace que el almacenamiento sea menos eficiente, y todas mis ganancias se obtienen reduciendo el número de caracteres almacenados en cada fila.

+6

Obviamente sqlite es un formato binario, mientras que csv es texto. La diferencia de tamaño del 60% puede ser causada por eso. –

+1

Disculpa, ¿qué es el tiempo de salud? Una búsqueda rápida en Google no generó nada. –

+0

healthtime es solo el nombre del campo. – Maus

Respuesta

23

SQLite no ejecuta un algoritmo de compresión, pero almacenará datos en un archivo binario en lugar de un archivo de texto. Lo que significa que los datos pueden almacenarse de manera más eficiente, por ejemplo, utilizando un número de 32 bits (4 bytes) para representar 10,000,000 en lugar de almacenarlo como 8 bytes de texto (o más si el archivo es unicode).

Aquí hay más detalles sobre el SQL Database File Format si está interesado.

¿Tiene sentido?

+4

Vale la pena señalar que SQLite solo usa tantos bytes como sea necesario. Por ejemplo, el valor 7 solo necesita un byte. –

+2

El valor 7 necesita dos bytes: una varianza de tipo serie que sería de un byte de longitud en este caso, y el valor que sería un byte en este caso. El tipo de serie está presente para cada valor en la base de datos, es un byte para nulos y números, y tiene una longitud variable de hasta 9 bytes para blobs y texto. Entonces, por ejemplo, un entero largo de 32 bits toma 5 bytes, un flotante de 64 bits tiene 9 bytes, ya que en ambos casos tiene un tipo de serie de un byte. – thomasrutter

17

SQLite, de forma predeterminada, no comprime los datos que escribe en el disco; sin embargo, SQLite tiene un conjunto de "Extensiones propietarias" para eso y para otros fines. Busque ZIPVFS en los enlaces de la siguiente manera.

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

Se puede lograr una gran cantidad de "compresión" en sus datos mediante la codificación de campos como enteros. Por ejemplo, una dirección IP fue diseñada para encajar en una palabra (4 bytes).Cada octeto de la dirección puede representarse en un byte de una palabra.

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]) 

Además, su marca de tiempo se puede representar en el tiempo Unix, que es el número de segundos desde la época.

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

See the Date and Time functions

Nota CAST la directiva en el SQL anterior: SQLite no cumplir tipo en una columna, lo que puede tener un grupo de dígitos almacenados como una cadena; aumentando el tamaño de su campo más de lo necesario (esto también hará que ciertas consultas se comporten de manera extraña).

Una cosa más: el tamaño del campo no es la única parte de la historia. Recuerde que los índices ocupan también un espacio, y los índices en enteros son más eficientes, en términos de tamaño y rendimiento del disco.