基于lmdb存储引擎的python数据库库
pynndb的Python项目详细描述
pynndb-python本机nosql数据库
pynndb是pymamba的第二次迭代,名称更改反映了与另一个项目的冲突 名称相同,新旧版本的api之间存在一定程度的不兼容。AT 这一次,项目的核心部分应该被认为是相对稳定的(beta),并且 用于生产系统。orm模块是实验性的/alpha,并且非常有限 在复制模块未完成/处于实验状态且仍需要工作的情况下进行测试。
pynndb是基于lmdb存储引擎的基于键/值的nosql数据库。如果您希望访问 数据库从一个低级语言,如C/C++/Java,那么您可能会发现更快的数据库选项。然而, 如果您只想从python访问数据库,那么您可能会发现pynndb比 更传统的选择。
它有哪些稳定的功能?
- 可变长度记录,每个记录都存储在与mongo兼容的uuid中
- 记录作为python dict对象读/写
- 基于记录内容的lambda函数的二级索引
- 辅助索引上的重复键
- ACID事务处理
- 多线程和多进程访问以绕过gil性能限制
我可以尝试哪些功能?
- 原生命令行shell[ pynndb 文档在这里]
正在开发哪些功能?
- 高速多节点复制
- 阅读DOCS文档
- 本机对象关系映射器,通常用于SQL数据库,松散地基于SQLAlchemy
一些基本示例
这是一个如何创建名为my database的新数据库的示例,然后在该数据库中创建名为people的表,然后添加一些people。(这都来自python shell)
frompynndbimportDatabasedb=Database('my-database')people=db.table('people')people.append({'name':'Fred Bloggs','age':21})people.append({'name':'Joe Smith','age':22})people.append({'name':'John Doe','age':19})
现在有很多从数据库中恢复信息的方法,最简单的方法就是使用find()来扫描整个表。当find返回生成器时,您可以在for循环中使用它,也可以使用list将结果作为单个list对象恢复。
>>>fordocinpeople.find():...print(doc)...{'_id':b'58ed69161839fc5e5a57bc35','name':'Fred Bloggs','age':21}{'_id':b'58ed69211839fc5e5a57bc36','name':'Joe Smith','age':22}{'_id':b'58ed69301839fc5e5a57bc37','name':'John Doe','age':19}
注意,返回的记录包含一个id字段,这与mongo使用的objectid字段几乎相同,只是我们返回的是一个简单的字节字符串,而不是objectid类。当与python的新"format"函数匹配时,处理这种形式的数据的一个很好的特性是能够像这样轻松地格式化这些数据;
>>>fordocinpeople.find():...print('Name: {name:20} Age:{age:3}'.format(**doc))...Name:FredBloggsAge:21Name:JoeSmithAge:22Name:JohnDoeAge:19
或者,如果我们只需要数据的一个子集,我们可以使用一个匿名函数来过滤我们的结果;(注意,这是一个带过滤器的线性/顺序扫描)
>>>fordocinpeople.find(expression=lambdadoc:doc['age']>21):...print('Name: {name:20} Age:{age:3}'.format(**doc))...Name:JoeSmithAge:22
索引
透明索引是任何数据库系统的一个关键部分,我在tryi中挣扎了一段时间决定使用哪种机制。一方面,我希望能够通过复合字段和函数索引表,另一方面,我只希望能够简单地基于一个干净的字段进行索引。最后我决定了以下几点;
>>>people.ensure('by_name','{name}')>>>people.ensure('by_age_name','{age:03}{name}')
如果您非常熟悉python格式字符串,那么您将很快看到这里发生的事情,实际上我们只是通过表达式进行索引,但是当以dict格式提供记录时,表达式来自python格式字符串。因此,您不能直接使用函数来执行与密钥生成有关的任何操作,但是您可以使用python格式的mini语言执行很多操作。(对于任何能够想到必须具备的用例的人来说,添加实际功能都相对容易)
因此,一旦我们有了索引,我们就可以使用索引进行搜索,也可以根据索引的顺序查找记录,这样我们就可以重复使用find,但这次要为它提供一个可使用的索引;
>>>fordocinpeople.find('by_age_name'):...print('Name: {name:20} Age:{age:3}'.format(**doc))...Name:JohnDoeAge:19Name:FredBloggsAge:21Name:JoeSmithAge:22
或者我们可以查找特定的记录;
>>>people.seek_one('by_name',{'name':'Joe Smith'}){'_id':b'58ed69211839fc5e5a57bc36','name':'Joe Smith','age':22}
或者我们可以查找一系列记录;
>>>fordocinpeople.range('by_name',{'name':'J'},{'name':'K'}):...print('Name: {name:20} Age:{age:3}'.format(**doc))...Name:JoeSmithAge:22Name:JohnDoeAge:19
更新记录
我们已经介绍了向数据库中添加新记录,这样就可以更新和删除记录。这个怎么样;
>>>person=people.seek_one('by_name',{'name':'Joe Smith'})>>>person['age']+=1>>>people.save(person)>>>people.seek_one('by_name',{'name':'Joe Smith'}){'_id':b'58ed69211839fc5e5a57bc36','name':'Joe Smith','age':23}
以及删除;
frompynndbimportDatabasedb=Database('my-database')people=db.table('people')people.append({'name':'Fred Bloggs','age':21})people.append({'name':'Joe Smith','age':22})people.append({'name':'John Doe','age':19})0
还有很多事情要做,但到目前为止,它看起来很有希望。在我的工作站上,基于find的for循环每秒产生大约200k个结果,append每秒产生大约30k个新项。对于一个高级语言数据库来说,这似乎是相当值得尊敬的,并且在与python或node一起使用时,它似乎比mongo快得多。
frompynndbimportDatabasedb=Database('my-database')people=db.table('people')people.append({'name':'Fred Bloggs','age':21})people.append({'name':'Joe Smith','age':22})people.append({'name':'John Doe','age':19})1