前段时间要用最大熵进行自动分词和新词抽取,在处理小文本的时候没什么问题,直接将候选词及其频率、邻接词等信息存入词典放入内存即可。但后来要处理大文本,候选词太多直接导致MemoryError了,就想着先将候选词的信息放入硬盘,虽然降低了点儿速度,但至少也能跑出来结果。所以就找到了比较好用且存储性能较好的Berkeley DB,更棒的是Python自带处理模块——bsddb(Python3以后版本不再自带)。
Berkeley DB与传统的关系数据库不太一样,它存储的是“key-value”这样的键值对,更像是一个词典。而且value只能是字符类型,但毕竟其他类型都能转化为字符串,所以也无所谓了。比如在我的项目里,我就直接存的json数据,存的时候dumps进去,用的时候loads进来,很是方便。
Berkeley DB根据数据量以及用途的不同,可选择三种数据访问模式:btree、hash、queue、recno,四种模式简单说明下:
btree:用树结构存储数据,查询速度很快,可以存储任意复杂的key和value;
hash:用hash算法存储数据,速度和btree差不多,只是当数据量特别巨大时,使用hash效果更好;
queue:是队列操作,它有一个限制,只能存储定长的数据,也就是说value的长度是固定的!但是queue可以保持数据的先进先出,并且对数据的插入做了特殊的优化,并且提供行级锁,此外queue的key必须是数字;
recno:和queue类似,但是它支持变长的value,它的key同样也需要是数字。
打开数据库:
打开数据库进行数据操作的传统方法是先打开一个数据库环境,然后再打开数据库,如下以python为例:
def __init__(self):
home = "word_freq_db" # 数据库存放文件夹
self.filename = "word_freq.db" # 数据库名称
try:
os.mkdir(home) # 创建存放文件夹
except:
pass
self.dbenv = bsddb.db.DBEnv() # 数据库环境对象
self.dbenv.open(home, bsddb.db.DB_CREATE | bsddb.db.DB_INIT_MPOOL)
self.db = bsddb.db.DB(self.dbenv) # 数据库对象
self.db.open(self.filename, bsddb.db.DB_HASH, bsddb.db.DB_CREATE, 0666)
这里我将数据库操作封装到了一个类里,创建类即打开数据库。打开数据库时刻选择数据访问方法,如这里用“bsddb.db.DB_HASH”指定用hash模式访问数据库
python中还可用另一种比较简单的方式直接打开数据库
db = bsddb.hashopen() # 以hash模式打开数据库
当然,其他还有btopen()、rnopen()等。
读写数据:
读写数据也很是简单,就是将一对“key-value”写入数据库或从数据库中读出即可。如下以python为例
def write_to_db(self, key, value):
self.db.put(key, value);
def read_from_db(self, key):
return self.db.get(key)
获取key值列表:
# 获取key值列表
def get_db_keys(self):
return self.db.keys()
遍历数据库:
要遍历数据库,首先需要将cursor置于第一条数据,然后利用next方法以此访问数据直至结尾
record = db.cursor().first()
while record:
key = record[0]
value = record[1]
record = db.cursor().next()
first()和next()方法返回的是key-value组成的元组
删除数据记录:
确切地说,应该是根据key值删除一条数据,对应方法是db.delete(key)