2012-05-30 29 views
16

我有一个7.4GB的csv文件。在将其转换为具有python script的sqlite数据库后,输出DB为4.7Gb,大约为原始大小的60%。sqlite3压缩数据吗?

csv有大约150,000,000行。它有头:

tkey,ipaddr,healthtime,numconnections,policystatus,activityflag 

每一行看起来像

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

脚本使用healthtime将数据分成表192表

当我第一次看到这些数字,我认为我在某个地方犯了一个错误。对于只增加健康时间192次而不是150,000,000次的附加效率,我应该期望减少多少文件大小?

编辑:只要我发布这个,我意识到了答案。我删除了大约40%的字符串,因此缩小了40%。

编辑2让我们来计算的纯文本之间的尺寸差:

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

和数据库条目:

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

首先,我们从46到26个字符下降以纯文本表示。

剩余字符是:

"261846,172.10.28.15,22,1,1" 

或26字节。如果每个整数需要存储在32位(4字节),那么我们有:

12字节(ipaddr)+ 4字节* 4(整数字段)= 28字节。

所以它看起来像转换为整数使得存储稍微低效,我的所有收益来形成减少存储在每一行中的字符数。

+6

很明显,sqlite是一种二进制格式,而csv是文本。 60%的尺寸差异可能是由此造成的。 –

+1

对不起,什么是健康状况?一个快速的谷歌搜索没有变成什么。 –

+0

健康时间只是该领域的名称。 – Maus

回答

23

SQLite未运行压缩算法,但它将数据存储在二进制文件而不是文本文件中。这意味着可以更高效地存储数据,例如使用32位(4字节)的数字来表示10,000,000,而不是将其存储为8字节的文本(如果文件是unicode,则更多)。

如果您有兴趣,以下是SQL Database File Format的更多详细信息。

这有道理吗?

+4

值得指出的是,SQLite只使用尽可能多的字节。例如,值7只需要一个字节。 –

+2

值7需要两个字节:一个串行类型varint,在这种情况下可以是一个字节长,在这种情况下可以是一个字节的值。串行类型对数据库中的每个值都是存在的,它对于空值和数字是一个字节,并且对于斑点和文本而言是可变长度,最大为9个字节。所以,例如,一个32位长的整数需要5个字节,64位的浮点数是9个字节,因为在这两种情况下它都有一个字节的串行类型。 – thomasrutter

17

默认情况下,SQLite不压缩写入磁盘的数据;然而,SQLite确实有一套“专有扩展”用于这个目的和其他目的。在链接中查找ZIPVFS,如下所示。

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

您可以通过编码领域整数实现很多你的数据“压缩”的。例如,IP地址被设计为适合一个字(4字节)。地址的每个八位字节可以用一个字的一个字节表示。

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

此外,您的时间戳可以在Unix时间,这是因为时代的秒数来表示。

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

See the Date and Time functions

注意CAST指令在上面的SQL:SQLite不列上强制执行的类型,所以你可能有一组存储为一个字符串的数字;不必要地增加字段大小(这也会使某些查询行为异常)。

还有一件事:字段大小不是故事的唯一部分。请记住,索引也占用一个空间,整数索引更有效率 - 根据磁盘大小和性能。