Berkeley-db
前言:
文件数据库不需要太大的内存,只需要足够的磁盘,就可以快速检索key获得value, 真是不错,记录下来。
Berkeley DB是历史悠久的嵌入式数据库系统,主要应用在UNIX/LINUX操作系统上,其设计思想是简单、小巧、可靠、高性能。
Berkeley DB (DB)是一个高性能的,嵌入数据库编程库,和C语言,C++,Java,Perl,Python,PHP,Tcl以及其他很DB可以支持数千的并发线程同时操作数据库,支持最大256TB的数据,广泛多语言都有绑定。Berkeley DB可以保存任意类型的键/值对,而且可以为一个键保存多个数据。
Python下使用Berkeley-db
安装:
Linux下安装
yum install gcc
wget http://download.oracle.com/berkeley-db/db-5.3.21.tar.gz
tar -zxvf db-5.3.21.tar.gz
cd db-5.3.21
cd build_unix/
../dist/configure #默认安装在/usr/local/BerkeleyDB.5.3下
make
sudo make install
wget http://pypi.python.org/packages/source/b/bsddb3/bsddb3-5.3.0.tar.gz#md5=d5aa4f293c4ea755e84383537f74be82
tar -zxvf bsddb3-5.3.0.tar.gz
cd bsddb3-5.3.0
sudo python setup.py --lflags="/usr/local/BerkeleyDB.5.3/lib/libdb-5.3.so" install
sudo python setup.py --berkeley-db="/usr/local/BerkeleyDB.5.3" install
Windows下安装,主要下载berkeley-db不同,其它类似
http://download.oracle.com/otn/berkeley-db/db-6.1.26.msi?AuthParam=1437466365_8ca86e8d1163cbdb497f860b606fb006
测试:
- 判断安装是否正确
#python
>import bsddb
>import bsddb3 as bsddb
如果引入bsddb失败,可能是版本不同,需要引入bsddb3
- 基本使用
>>> import bsddb3 as bsddb
>>> db = bsddb.btopen('spam.db', 'c')
>>> for i in range(10): db['%d'%i] = '%d'% (i*i)
...
>>> db['3'] #获取某个值
'9'
>>> db.keys() #获取所有值
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
>>> db.first() #第一个值
('0', '0')
>>> db.next() #下一个值
('1', '1')
>>> db.last() #最后一个值
('9', '81')
>>> db.set_location('2') #移动当前指针位置
('2', '4')
>>> db.previous() #当前指针前一个位置值
('1', '1')
>>> for k, v in db.iteritems(): #遍历所有 key 和value
... print k, v
0 0
1 1
2 4
3 9
4 16
5 25
6 36
7 49
8 64
9 81
>>> '8' in db #判断key是否存在
True
>>> db.sync() #写入数据库
0
import bsddb3 as bsddb
from datetime import datetime
print datetime.now()
db = bsddb.btopen('test-1.db','c') #c 表示创建数据库文件
for i in range(500000000):
db['%d'%i] = '%d' %(i)
db.sync()
db['1000'] = '1'
db['1000'] = '2'
print db['1000']
print db['499999999']
print db.has_key('499999999')
print db.has_key('100')
print db.first()
print db.last()
print db.set_location('499999999')
print len(db)
print datetime.now()
遍历数据库
当数据库中key特别多时,遍历数据库很慢,这时需要使用该数据库的,顺序查找的方式,会增加速度
import bsddb3 as bsddb
hash_tb = bsddb.btopen('md5_digit_8_0') #只读方式打开数据库
last = list(hash_tb.last()) #获得最后一个元素
key = last[0]
print hash_tb.set_location(key) #设置最后一个位置
count = 0
try:
while True:
count = count + 1
ck = list(hash_tb.previous()) #
print hash_tb.previous()
except Exception,e:
print e
print count
备注:
当导入大量记录发现 当记录数 多余1kw,在导入非常慢。但是将导入的key 排序后在导入,经测试导入速度是 4秒种 100w条记录。 10亿条记录仅需要一个小时(如果是ssd磁盘可能更快,条件有限,没有测试). 查询一条记录时间 是0.02秒
原来不排序导入数据,bdb是在随机读取读写数据,如果排序后,在导入可以减少碎片,压缩磁盘空间
但是大量数据进行排序,本身就是非常耗费时间,怎样使用berkeley-db进行大数据处理?
经测试当写入的数据非排序数据,在到达1kw将产生感觉到变慢,因此以1kw为单位,当记录数到达1kw,则分文件存储,发现通过遍历多个1kw,比遍历一个大文件要快的多的多。如下面的测试代码,遍历目录下文件,如果存在记录,则不处理,否则增加记录到文本数据库中。
def is_has_domain(domain):
global count
path = r'F:\alldomain'
for t in os.listdir(path):
filename = os.path.join(path,t)
tmp = bsddb.btopen(filename)
if domain in tmp:
return True
dbindex = count / 10000000
path = r'F:\alldomain'
filename = os.path.join(path, 'db-%d' % dbindex)
idb = bsddb.btopen(filename, 'c')
idb[domain] = ''
idb.sync()
idb.close()
return False
参考文献:
oracle官方文档
http://docs.oracle.com/cd/E17076_04/html/index.html
python berkeley-db官方文档
https://docs.python.org/2/library/bsddb.html
bsddb3 代替bsddb
经验总结