把Sqlite当嵌入式KV数据库用
市面上已经有很优秀的嵌入式KV数据库了,如Berkeley DB。为什么还需要把Sqlite当KV数据库用呢?原因若干。
1,可能是为了好玩或者纯属无聊
2,可结合关系型数据库与KV数据库的优点
3,可利用一些sqlite特性做其他KV数据库不好做的事情
4,事务管理更方便
5,sqlite更可靠,更流行
实现思路
使用json(或pickle)dump数据,并将数据写入有KEY(主键)和VALUE两个字段的SQLITE库表中。参照kv数据库调用办法实现外部接口。
主要功能
1,put:写入key/value数据
2,get:获取某个key的value
3,put_many:批量写入key/value数据
4,keys:获取所有key的列表
5,value:获取所有value的列表
6,limit:利用SQL语句中limit关键字,获取数据库中“前”N条KV数据
7,random:利用SQL语句中random关键字,从数据库中随即获取N条KV数据
8,has_key:某个key是否存在
9,cursor_execute:执行sql自定义语句
10,其他:items,pop,filter,count等
代码(KVSqlite.py):
import os, json, sqlite3
from threading import LockPY3 = os.sys.version_info >= (3,)
if PY3:ifilter = filter
else:from itertools import ifilterDUMPS = lambda d: json.dumps(d)
LOADS = lambda d: json.loads(d)class SDB(object):_DEFAULT_TABLE = '__KVS_DEFAULT_TABLE__'_MEMORY_DB = ":memory:"def __init__(self, filename):if filename is None \or len(filename) < 1 \or filename.lower() == self._MEMORY_DB:self.filename = self._MEMORY_DBelse:self.filename = filenameself._lock = Lock()self._db_init()def _row_factory(self, cursor, row):result = []for idx, col in enumerate(cursor.description):if col[0].lower() in ('k', 'v'):result.append(LOADS(row[idx]))else:result.append(row[idx])return resultdef _db_init(self):_new_table = "CREATE TABLE IF NOT EXISTS {0} ( k PRIMARY KEY,v)".format(self._DEFAULT_TABLE)db = sqlite3.connect(self.filename, timeout=60, check_same_thread=False)db.row_factory = self._row_factorydb.execute(_new_table)self._cursor = db.cursor()self._db = dbdef _statement_init(self):table = self._DEFAULT_TABLEreturn dict(insert="insert or replace into {0}(k,v) values(:1,:2)".format(table),delete="delete from {0} where k=:1".format(table),update="update {0} set v=:1 where k=:2".format(table),clear="delete from {0}".format(table),get="select v from {0} where k=:1".format(table),has_key="select count(1) from {0} where k=:1".format(table),keys="select k from {0}".format(table),values="select v from {0}".format(table),items="select k,v from {0}".format(table),count="select count(*) from {0}".format(table),random="select * from {0} order BY RANDOM() limit :1".format(table),limit="select * from {0} limit :1 offset :2".format(table))_statements = property(_statement_init)del _statement_initdef _insert(self, key, value):try:self._lock.acquire(True)self._cursor.execute(self._statements.get('insert'), (DUMPS(key), DUMPS(value)))finally:self._lock.release()def _update(self, key, value):try:self._lock.acquire(True)self._cursor.execute(self._statements.get('update'), (DUMPS(value), DUMPS(key)))finally:self._lock.release()def _delete(self, key):try:self._lock.acquire(True)self._cursor.execute(self._statements.get('delete'), (DUMPS(key),))finally:self._lock.release()def _clear(self):'''删除所有数据:return:'''try:self._lock.acquire(True)self._cursor.execute(self._statements.get('clear'))except Exception as e:self._db.rollback()raise efinally:self._lock.release()def keys(self, sort=False, sort_key=None, reverse=False):if sort:return sorted(self.iterkeys(), key=sort_key, reverse=reverse)return list(self.iterkeys())def values(self, sort=False, sort_key=None, reverse=False):if sort:return sorted(self.itervalues(), key=sort_key, reverse=reverse)return list(self.itervalues())def iterkeys(self):try:self._lock.acquire(True)for k in self._cursor.execute(self._statements.get('keys')):yield k[0]finally:self._lock.release()def itervalues(self):try:self._lock.acquire(True)for v in self._cursor.execute(self._statements.get('values')):yield v[0]finally:self._lock.release()def items(self, sort=False, key=None, reverse=False):if sort:return sorted(self.iteritems(), key=key, reverse=reverse)return list(self.iteritems())def iteritems(self):try:self._lock.acquire(True)for k, v in self._cursor.execute(self._statements.get('items')):yield k, vfinally:self._lock.release()def count(self):try:self._lock.acquire(True)return self._cursor.execute(self._statements.get('count')).fetchone()[0]finally:self._lock.release()def has_key(self, key):try:self._lock.acquire(True)r = self._cursor.execute(self._statements.get('has_key'), (DUMPS(key),)).fetchone()[0]return r > 0finally:self._lock.release()def get(self, key):try:self._lock.acquire(True)_key = DUMPS(key)data = self._cursor.execute(self._statements.get('get'), (_key,)).fetchone()if data:return data[0]finally:self._lock.release()def put(self, key, value):try:self._insert(key, value)self._db.commit()except Exception as e:self._db.rollback()raise edef pop(self, key):try:value = self.get(key)self._delete(key)self._db.commit()return valueexcept Exception as e:self._db.rollback()raise edef put_many(self, rows):try:self._lock.acquire(True)if rows and len(rows) > 0:self._cursor.executemany(self._statements.get('insert'),[(DUMPS(k), DUMPS(v)) for k, v in rows])self._db.commit()except Exception as e:self._db.rollback()raise efinally:if self._lock.locked():self._lock.release()def limit(self, limit=1, offset=0):try:self._lock.acquire(True)rows = self._cursor.execute(self._statements.get('limit'), (limit, offset))if limit == 1:return rows.fetchone()return rows.fetchall()finally:self._lock.release()def random(self, limit=1):try:self._lock.acquire(True)rows = self._cursor.execute(self._statements.get('random'), (limit,))if limit == 1:return rows.fetchone()return rows.fetchall()finally:self._lock.release()def filter(self, func):return list(ifilter(func, self.items()))def ifilter(self, func):return ifilter(func, self.iteritems())def cursor_execute(self, sql, parameters=None):'''执行SQL语句,如:SELECT K,V FROM __KVS_DEFAULT_TABLE__ WHERE K LIKE 'ABC%''''try:self._lock.acquire(True)return self._cursor.execute(sql=sql, parameters=parameters)finally:self._lock.release()def close(self):try:self._db.rollback()self._cursor.close()self._db.close()except:pass
调用示例:
from KVSqlite import SDB
#打开数据库
db = SDB('test.sqlite')
#写入单条数据
db.put('first','第一条数据')
db.put('second',dict(a=1,b=2,c=[2,3,4]))
#获取数据
db.get('first')
#写入多条数据
db.put_many([[1,2],[3,4],['A','abc']])
#获取key的列表
db.keys()
把Sqlite当嵌入式KV数据库用相关推荐
- 计划实现一个开源的KV数据库——Simple DB
实现一个开源KV数据库的想法来源于对目前项目中所使用的K-V数据库使用情况的不满意. 先介绍一下我们的目前项目,作为本文的背景: 较为底层的分布式运行平台,使用C/C++实现的Actor模型(异步消息 ...
- sqlite c++插入 timestamp_Dqlite,基于sqlite 高可用(HA)数据库
原文发表于我的博客, 特此版权声明 noosphere.site: Dqlite,基于sqlite 高可用(HA)数据库 csdn : Dqlite,基于sqlite 高可用(HA)数据库 k3s之前 ...
- 大数据入门(SQLite手机本地轻量级数据库增删改查)
SQLite手机本地轻量级数据库 数据库分为: 1.关系型数据库(mysql主外键属于关系型) 2.对象型数据库(oracle) 3.嵌入式数据库 案例: 安卓控件(5个Button)访问Activi ...
- 同时支持三个mysql+sqlite+pdo的php数据库类_同时支持三个MySQL+SQLite+PDO的PHP数据库类...
PHP学习教程文章简介: 同时支持三个MySQL+SQLite+PDO的PHP数据库类使用方法: // mysql connect $db = new SQL(mysql:host=localhost ...
- sqlite管理工具_Liquibase 数据库版本管理工具:1.安装
1.Liquibase 是什么 粘一段官方的解释 Track, version, and deploy database changes 跟踪.管理和应用数据库变化 说白了,就是一个将你的数据库脚本转 ...
- SQLite和NPoco的数据库初始化器
目录 介绍 IDbInitialiser IDatabaseConfigurator 示例实现 注意事项 下载源代码 - 49.7 KB 介绍 这篇文章是在我创建一个小型博客风格的Web应用程序时出现 ...
- typechoSQLIte转MySQL_Typecho SQLite与MySQL的数据库切换及解决MySQL连接打开缓慢问题
(本科水平,写得不好请不吝指点 ) Ⅰ Abstract Typecho开源轻量级博客系统拥有WordPress主题插件二次开发等一系列优点,但相比于WordPress笨重复杂的操作,Typecho赢 ...
- 如何设计一个简单的KV数据库
下面的内容仅供设计一个简单的KV数据库.如果想要实现一个功能更强的KV数据库的话,还需要考虑:更加丰富的数据类型.数据压缩.过期机制.数据淘汰策略.集群化.高可用等功能,另外还可以增加统计模块.通知模 ...
- mysql做kv数据库_如何将SQL数据映射到KV数据库
日常吐槽 国外文章也不是都是好文章啊,不要见到英文就觉得高大上了-- 前言 越来越多的关系型数据库底层选择基于KV构建,例如TiDB的TiKV(RocksDB),cockroach的levelDB,M ...
最新文章
- ps -ef 的含义
- spring 定时器任务深入理解
- TINYINT,SMALLINT,MEDIUMINT,INT,INTEGER,BIGINT;text,longtext,mediumtext,ENUM,SET等字段类型区别
- Star 10.9K!这份Google面试攻略,牛逼了!
- spring @Transactional注解参数详解
- 一阶网络相应特性的研究_36、 用一阶系统描述的传感器,其动态响应特征的优劣也主要取决于时间常数τ,τ越大越好。( )...
- Kali获取不到IP解决方案
- C语言大神进来看看这个题目
- 美团关联公司公开“无人车及无人配送系统”相关专利
- Ant Design Pro引入Echarts 报错Unexpected token
- 蓝桥杯 历届试题 剪格子(dfs搜索)
- 百度手机输入法,如何使用五笔98版?
- leetcode记录-罗马数字转整数
- ubuntu上常用的软件安装
- Nginx#Nginx-Typora笔记
- 15.3,python中扫描条形码和二维码
- 导致无线网卡连接不上wifi的几种原因|为什么无线网卡连不上wifi?
- 福州黑白风格的婚纱照拍摄介绍
- See!AI正在悄然改变着医学诊断、假肢和视觉辅助
- wordpress友联_WordPress 友情链接页面终极版