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

http://marc-abramowitz.com/archives/2007/11/28/hacking-os-xs-python-dbhash-and-bsddb-modules-to-work/

经验总结

http://blog.chinaunix.net/uid-23145525-id-3499930.html

results matching ""

    No results matching ""