1 初探
在平时的开发工作中,我们可能会有这样的需求:我们希望有一个内存数据库或者数据引擎,用比较Pythonic的方式进行数据库的操作(比如说插入和查询)。
举个具体的例子,分别向数据库db中插入两条数据,”a=1, b=1″ 和 “a=1, b=2”, 然后想查询a=1的数据可能会使用这样的语句db.query(a=1),结果就是返回前面插入的两条数据; 如果想查询a=1, b=2的数据,就使用这样的语句db.query(a=1, b=2),结果就返回前面的第二条数据。
那么是否拥有实现上述需求的现成的第三方库呢?几经查找,发现PyDbLite能够满足这样的需求。其实,PyDbLite和Python自带的SQLite均支持内存数据库模式,只是前者是Pythonic的用法,而后者则是典型的SQL用法。
他们具体的用法是这样的:
PyDbLite
SQLite
2 pydblite和sqlite的性能
毫无疑问,pydblite的使用方式非常地Pythonic,但是它的效率如何呢?由于我们主要关心的是数据插入和查询速度,所以不妨仅对这两项做一个对比。写一个简单的测试脚本:
在创建索引的情况下,10w次的插入和查询的时间如下:
在未创建索引的情况(把创建索引的测试语句注释掉)下,1w次的插入和查询时间如下:
我们不难得出如下结论:
sqlite的插入速度是pydblite的3-5倍;而在建立索引的情况下,sqlite的查询速度和pydblite相当;在未建立索引的情况下,sqlite的查询速度比pydblite慢1.5倍左右。
3 优化
我们的目标非常明确,使用Pythonic的内存数据库,提高插入和查询效率,而不考虑持久化。那么能否既拥有pydblite的pythonic的使用方式,又同时具备pydblite和sqlite中插入和查询速度快的那一方的速度?针对我们的目标,看看能否对pydblite做一些优化。
阅读pydblite的源码,首先映入眼帘的是对python2和3做了一个简单的区分。给外部调用的Base基于_BasePy2或者_BasePy3,它们仅仅是在__iter__上有细微差异,最终调用的是_Base这个类。
然后看下_Base的构造函数,做了简单的初始化文件的操作,由于我们就是使用内存数据库,所以文件相关的内容完全可以抛弃。
紧接着比较重要的是create(创建字段)、create_index(创建索引)两个函数:
可以看出,pydblite在内存中维护了一个名为records的字典变量,用来存放一条条的数据。它的key是内部维护的id,从0开始自增;而它的value则是用户插入的数据,为了后续查询和记录的方便,这里在每条数据中额外又加入了__id__和__version__。其次,内部维护的indices字典变量则是是个索引表,它的key是字段名,而value则是这样一个字典:其key是这个字段所有已知的值,value是这个值所在的那条数据的id。
举个例子,假设我们插入了“a=-1,b=0,c=1”和“a=0,b=1,c=2”两条数据,那么records和indices的内容会是这样的:
比方说现在我们想查找a=0的数据,那么就会在indices中找key为’a’的value,即{-1: set([0]), 0: set([1])},然后在这里面找key为0的value,即[1],由此我们直到了我们想要的这条数据它的id是1(也可能会有多个);假设我们对数据还有其他要求比如a=0,b=1,那么它会继续上述的查找过程,找到a=0和b=1分别对应的ids,做交集,就得到了满足这两个条件的ids,然后再到records里根据ids找到所有对应的数据。
明白了原理,我们再看看有什么可优化的地方:
数据结构,整体的records和indeices数据结构已经挺精简了,暂时不需要优化。其中的__version__可以不要,因为我们并不关注这个数据被修改了几次。其次是由于indices中最终的ids是个list,在查询和插入的时候会比较慢,我们知道内部维护的id一定是唯一的,所以这里改成set会好一些。
python语句,不难看出,整个_Base为了同时兼容python2和python3,不得不使用了2和3都支持的语句,这就导致在部分语句上针对特定版本的python就会造成浪费或者说是性能开销。比如说,d是个字典,那么为了同事兼容python2和3,作者使用了类似与for key in d.keys()这样的语句,在python2中,d.keys()会首先产生一个list,用d.iterkeys是个更明智的方案。再如,作者会使用类似set(d.keys()) – set([1])这样的语句,但是python2中,使用d.viewkeys() – set([1])效率将会更高,因为它不需要将list转化成set。
对特定版本python的优化语句就不一一举例,概括地说,从数据结构,python语句以及是否需要某些功能等方面可以对pydblite做进一步的优化。前面只是说了create和create_index两个函数,包括insert和__call__的优化也十分类似。此外,用普通方法来代替魔法方法,也能稍微提升下效率,所以在后续的优化中将__call__改写为了query。
优化后的代码,请见MemLite。
4 memlite、pydblite和sqlite的性能
让我们在上文的测试代码中加入对memlite的测试:
在创建索引的情况下,10w次的插入和查询的时间如下:
在未创建索引的情况(把创建索引的测试语句注释掉)下,1w次的插入和查询时间如下:
可以看出,在创建索引的情况下,memlite的插入和查询性能在sqlite和pydblite之上;而在未创建索引的情况下,memlite的插入性能和sqlite一样,好于pydblite,memlite的查询性能比pydblite稍差,但好于sqlite。综合来看,memlite即拥有pydblite的pythonic的使用方式,又拥有pydblite和sqlite中性能较高者的效率,符合预期的优化目标。
相关推荐
在本文中,我们将深入探讨如何在Delphi编程环境中利用SQLite3数据库系统,特别是关于本地数据库与内存数据库的使用。SQLite3是一种轻量级、自包含的数据库引擎,它不需要独立的服务器进程,使得在Delphi应用程序中...
SQLiteExpert是一款专为SQLite数据库设计的轻量级内存数据库管理工具,它提供了高效、便捷的方式来创建、管理和维护SQLite数据库。SQLite是一种开源、无服务器、自包含的SQL数据库引擎,广泛应用于移动设备、嵌入式...
在Delphi中,我们可以使用SQLite数据库引擎来创建和操作内存数据库。 SQLite是一个轻量级的、自包含的、开源的SQL数据库引擎,它可以运行在多种操作系统上,包括Windows、Linux和Mac OS X等。SQLite支持在内存中...
一、建立数据库 根据需求建立数据库,建立了两个表,并保证了可以将数据存储到已有的数据库中,代码如下: import sqlite3 def createDataBase(): cn = sqlite3.connect('check.db') cn.execute('''CREATE TABLE IF ...
SQLite是一款轻量级的、开源的、自包含的SQL数据库引擎,它可以在无需单独服务器进程或特殊权限的情况下运行。SQLite嵌入式到应用程序中,提供可靠的数据存储功能,尤其适用于移动设备和小型应用。在本教程中,我们...
python3.8在import sqlite3时报错误:ImportError: No module named '_sqlite3'。 将该文件解压后,放到python3.8目录下的lib-dynload目录下。 比如我的服务器路径:/usr/local/bin/python3/lib/python3.8/lib-...
在Python编程中,SQLite是一个轻量级的数据库引擎,它被集成在标准库之中,无需额外安装即可使用。SQLite提供了一种方便的方式来存储和管理数据,尤其适合小型项目或者作为应用程序的数据存储。本资料"Python操作...
python连接sqlite数据库并完成增删改等基本操作,主界面可视化显示。用户可根据提示输入数字实现相关功能。
SQLite是一个轻型的嵌入式数据库,它非常轻量级,占用的系统资源极少,通常只需要几百KB的内存即可运行。它不依赖于服务器进程,而是在应用程序内部运行,这一点与其他数据库有着本质的不同。SQLite支持标准的数据库...
go-sqlite3, 使用数据库/sql的for驱动程序 go-sqlite3 描述数据库/sql接口相符合的rtc驱动程序安装这个软件包可以用 go get命令安装:go get github.com/mattn/go-sqlite3go-sqli
SQLcrush是一款专为Python爱好者设计的基于命令行的数据库管理工具,它提供了一个简洁、高效的界面来操作SQLite数据库。尽管当前版本仅支持SQLite,但其潜在的扩展性意味着未来可能涵盖MySQL和PostgreSQL等其他流行...
Python 数据库编程 02操作sqlite3数据库插入数据.mp4
Python 数据库编程 03操作SQLite3数据库查询数据.mp4
这是一个基于Python的图书信息管理系统,使用了tkinter库来创建GUI图形界面,同时结合sqlite3数据库来存储和管理图书数据。这个系统对于初学者来说是一个很好的实践项目,它涵盖了多种编程和技术知识点,包括: 1. ...
在C#环境下SQLite加密/解密工具。包含源码
SQLite3是一种轻量级、开源的嵌入式数据库引擎,被广泛应用于各种应用程序中,特别是嵌入式系统和移动应用。在许多情况下,为了保护数据的安全性和隐私,对存储的数据进行加密是必要的。"sqlite3嵌入式数据库加密...
Python 数据库编程 04操作SQLite3数据库修改_删除数据.mp4
SQLite 定义 SQLite是嵌入式关系数据库管理系统。 它是独立的,无服务器的,零配置和事务性SQL数据库引擎 作用 可以自由地用于商业或私有的任何目的 本质 ... SQLite是python自带的数据库,
【Python操作数据库】 ...这个课件非常适合初学者和教师,通过一个综合案例详细展示了Python操作SQLite数据库的全过程,涵盖从数据库基础、SQL语句到Python API的使用,是学习和复习Python数据库操作的宝贵资源。
在Java下连接SQLite数据库 一、下载SQLite数据库的JDBC:http://www.zentus.com/sqlitejdbc/ 二、将下载到的包解压后得到jar包放到%JAVA_HOME%\lib下,并且将其添加到ClassPath系统环境变量中。一定要保证在类路径...