Python中的数据库压缩
我有像这样的小时日志Python中的数据库压缩,python,Python,我有像这样的小时日志 user1:joined user2:log out user1:added pic user1:added comment user3:joined 我想把所有的平面文件压缩成一个文件。日志中有大约3000万用户,我只想要所有日志的最新用户日志 我的最终结果是我想要一个像 user1:added comment user2:log out user3:joined 现在我的第一次小规模尝试就是做一个像dict一样的dict log['user1'] = "added
user1:joined
user2:log out
user1:added pic
user1:added comment
user3:joined
我想把所有的平面文件压缩成一个文件。日志中有大约3000万用户,我只想要所有日志的最新用户日志
我的最终结果是我想要一个像
user1:added comment
user2:log out
user3:joined
现在我的第一次小规模尝试就是做一个像dict一样的dict
log['user1'] = "added comment"
执行3000万个键/值对的dict是否会占用大量内存。。或者我应该使用类似sqllite的东西来存储它们。。然后,只需将sqllite表的内容放回一个文件中?如果您选择了每个日志条目,那么无论它显示多少次,对于每个类似的日志条目,您将只使用一个字符串,从而大大降低内存使用率
>>> a = 'foo'
>>> b = 'foo'
>>> a is b
True
>>> b = 'f' + ('oo',)[0]
>>> a is b
False
>>> a = intern('foo')
>>> b = intern('f' + ('oo',)[0])
>>> a is b
True
如果对每个日志条目都进行了修改,那么无论它显示多少次,对于每个类似的日志条目都只使用一个字符串,从而大大降低了内存使用率
>>> a = 'foo'
>>> b = 'foo'
>>> a is b
True
>>> b = 'f' + ('oo',)[0]
>>> a is b
False
>>> a = intern('foo')
>>> b = intern('f' + ('oo',)[0])
>>> a is b
True
对于Map/Reduce解决方案来说,这似乎是一个完美的问题。见:
例如。对于Map/Reduce解决方案来说,这似乎是一个完美的问题。见:
例如。您也可以反向处理日志行,然后使用一个集合跟踪您看到的用户:
s = set()
# note, this piece is inefficient in that I'm reading all the lines
# into memory in order to reverse them... There are recipes out there
# for reading a file in reverse.
lines = open('log').readlines()
lines.reverse()
for line in lines:
line = line.strip()
user, op = line.split(':')
if not user in s:
print line
s.add(user)
您还可以反向处理日志行,然后使用一个集合跟踪您看到的用户:
s = set()
# note, this piece is inefficient in that I'm reading all the lines
# into memory in order to reverse them... There are recipes out there
# for reading a file in reverse.
lines = open('log').readlines()
lines.reverse()
for line in lines:
line = line.strip()
user, op = line.split(':')
if not user in s:
print line
s.add(user)
模拟数据结构以查看需要多少内存非常容易 类似于此,您可以更改gen_字符串以生成与消息近似的数据
import random
from commands import getstatusoutput as gso
def gen_string():
return str(random.random())
d = {}
for z in range(10**6):
d[gen_string()] = gen_string()
print gso('ps -eo %mem,cmd |grep test.py')[1]
在单gig上网本上:
0.4 vim test.py
0.1 /bin/bash -c time python test.py
11.7 /usr/bin/python2.6 test.py
0.1 sh -c { ps -eo %mem,cmd |grep test.py; } 2>&1
0.0 grep test.py
real 0m26.325s
user 0m25.945s
sys 0m0.377s
。。。因此,它在100000条记录中使用了大约10%的1G
但这也取决于您有多少数据冗余…模拟数据结构以查看需要多少内存非常容易 类似于此,您可以更改gen_字符串以生成与消息近似的数据
import random
from commands import getstatusoutput as gso
def gen_string():
return str(random.random())
d = {}
for z in range(10**6):
d[gen_string()] = gen_string()
print gso('ps -eo %mem,cmd |grep test.py')[1]
在单gig上网本上:
0.4 vim test.py
0.1 /bin/bash -c time python test.py
11.7 /usr/bin/python2.6 test.py
0.1 sh -c { ps -eo %mem,cmd |grep test.py; } 2>&1
0.0 grep test.py
real 0m26.325s
user 0m25.945s
sys 0m0.377s
。。。因此,它在100000条记录中使用了大约10%的1G
但这也取决于您有多少数据冗余…各种dbm模块(Python3中的dbm,或Python2中的anydbm、gdbm、dbhash等)允许您创建键到值映射的简单数据库。它们存储在磁盘上,因此不会对内存造成巨大影响。如果愿意,您可以将它们存储为日志。各种dbm模块(Python3中的dbm,或Python2中的anydbm、gdbm、dbhash等)允许您创建键到值映射的简单数据库。它们存储在磁盘上,因此不会对内存造成巨大影响。如果愿意,您可以将它们存储为日志。感谢@Ignacio for intern()- 那么,问题是这将消耗多少内存
def makeUserName():
ch = random.choice
syl = ['ba','ma','ta','pre','re','cu','pro','do','tru','ho','cre','su','si','du','so','tri','be','hy','cy','ny','quo','po']
# 22**5 is about 5.1 million potential names
return ch(syl).title() + ch(syl) + ch(syl) + ch(syl) + ch(syl)
ch = random.choice
states = ['joined', 'added pic', 'added article', 'added comment', 'voted', 'logged out']
d = {}
t = []
for i in xrange(1000):
for j in xrange(8000):
d[makeUserName()] = ch(states)
t.append( (len(d), sys.getsizeof(d)) )
导致
(横轴=用户名数,纵轴=内存使用量(以字节为单位),这是。。。有点奇怪。它看起来像是一本字典预先分配了相当多的内存,然后每次太满时都会加倍
不管怎么说,400万用户占用的内存不到100MB,但实际上它重新分配了大约300万用户,50MB,因此如果双倍增长保持不变,您将需要大约800MB的内存来处理2400万到4800万用户。多亏了@Ignacio for intern()- 那么,问题是这将消耗多少内存
def makeUserName():
ch = random.choice
syl = ['ba','ma','ta','pre','re','cu','pro','do','tru','ho','cre','su','si','du','so','tri','be','hy','cy','ny','quo','po']
# 22**5 is about 5.1 million potential names
return ch(syl).title() + ch(syl) + ch(syl) + ch(syl) + ch(syl)
ch = random.choice
states = ['joined', 'added pic', 'added article', 'added comment', 'voted', 'logged out']
d = {}
t = []
for i in xrange(1000):
for j in xrange(8000):
d[makeUserName()] = ch(states)
t.append( (len(d), sys.getsizeof(d)) )
导致
(横轴=用户名数,纵轴=内存使用量(以字节为单位),这是。。。有点奇怪。它看起来像是一本字典预先分配了相当多的内存,然后每次太满时都会加倍
无论如何,400万用户占用的内存不到100MB,但实际上它重新分配了大约300万用户,50MB,因此如果双倍增长保持不变,您将需要大约800MB的内存来处理2400万到4800万用户。当然,但字典的密钥将自动唯一。当然,但是对于字典,该键将自动是唯一的。您是否对已记录的日志执行一次此操作,如果不执行,您希望日志在某个时间段内为id存储一个结果,还是永久存储?您是否对已记录的日志执行一次此操作,如果不执行,您希望日志在某个时间段内为id存储一个结果,还是永远?