让 Python 更加充分的使用 Sqlite3


我最近在涉及大量数据处理的项目中频繁使用 sqlite3。我最初的尝试根本不涉及任何数据库,所有的数据都将保存在内存中,包括字典查找、迭代和条件等查询。这很好,但可以放入内存的只有那么多,并且将数据从磁盘重新生成或加载到内存是一个繁琐又耗时的过程。


我决定试一试sqlite3。因为只需打开与数据库的连接,这样可以增加可处理的数据量,并将应用程序的加载时间减少到零。此外,我可以通过 SQL 查询替换很多Python逻辑语句。


我想分享一些关于这次经历的心得和发现。


TL;DR


  1. 使用大量操作 (又名 executemany)

  2. 你不需要使用光标 (大部分时间)。

  3. 光标可被迭代。

  4. 使用上下文管理器。

  5. 使用编译指示 (当它有意义)。

  6. 推迟索引创建。

  7. 使用占位符来插入 python 值。


1. 使用大量操作


如果你需要在数据库中一次性插入很多行,那么你真不应该使用 execute。sqlite3 模块提供了批量插入的方式:executemany。


而不是像这样做:


for row in iter_data():

connection.execute('INSERT INTO my_table VALUES (?)', row)


你可以利用这个事实,即 executemany 接受元组的生成器作为参数:


connection.executemany(

 'INSERT INTO my_table VALUE (?)',

    iter_data()

)


这不仅更简洁,而且更高效。实际上,sqlite3 在幕后利用 executemany 实现 execute,但后者插入一行而不是多行。


我写了一个小的基准测试,将一百万行插入空表(数据库在内存中):

  • executemany: 1.6 秒

  • execute: 2.7 秒


2. 你不需要游标


一开始我经常搞混的事情就是,光标管理。在线示例和文档中通常如下:


connection = sqlite3.connect(':memory:')

cursor = connection.cursor()

# Do something with cursor


但大多数情况下,你根本不需要光标,你可以直接使用连接对象(本文末尾会提到)。像execute和executemany类似的操作可以直接在连接上调用。以下是一个证明此事的示例:


import sqlite3

connection = sqlite3(':memory:')

# Create a table

connection.execute('CREATE TABLE events(ts, msg)')

# Insert values

connection.executemany(

 'INSERT INTO events VALUES (?,?)',

    [

        (1, 'foo'),

        (2, 'bar'),

        (3, 'baz')

    ]

)

# Print inserted rows

for row in connnection.execute('SELECT * FROM events'):

    print(row)


3. 光标(Cursor)可被用于迭代


你可能经常会看到使用fetchone或fetchall来处理SELECT查询结果的示例。但是我发现处理这些结果的最自然的方式是直接在光标上迭代:


for row in connection.execute('SELECT * FROM events'):

 print(row)


这样一来,只要你得到足够的结果,你就可以终止查询,并且不会引起资源浪费。当然,如果事先知道你需要多少结果,可以改用LIMIT SQL语句,但Python生成器是非常方便的,可以让你将数据生成与数据消耗分离。


4. 使用Context Managers(上下文管理器)


即使在处理SQL事务的中间,也会发生讨厌的事情。为了避免手动处理回滚或提交,你可以简单地使用连接对象作为上下文管理器。 在以下示例中,我们创建了一个表,并错误地插入了重复的值:


import sqlite3

connection = sqlite3.connect(':memory:')

with connection:

    connection.execute(

  'CREATE TABLE events(ts, msg, PRIMARY KEY(ts, msg))')

try:

    with connection:

        connection.executemany('INSERT INTO events VALUES (?, ?)', [

            (1, 'foo'),

            (2, 'bar'),

            (3, 'baz'),

            (1, 'foo'),

        ])

except (sqlite3.OperationalError, sqlite3.IntegrityError) as e:

    print('Could not complete operation:', e)

# No row was inserted because transaction failed

for row in connection.execute('SELECT * FROM events'):

    print(row)

connection.close()


5. 使用Pragmas


…当它真的有用时

在你的程序中有几个 pragma 可用于调整 sqlite3 的行为。特别地,其中一个可以改善性能的是synchronous:


connection.execute('PRAGMA synchronous = OFF')


你应该知道这可能是危险的。如果应用程序在事务中间意外崩溃,数据库可能会处于不一致的状态。所以请小心使用! 但是如果你要更快地插入很多行,那么这可能是一个选择。


6. 推迟索引创建


假设你需要在数据库上创建几个索引,而你需要在插入很多行的同时创建索引。把索引的创建推迟到所有行的插入之后可以导致实质性的性能改善。


7. 使用占位符插入 Python 值


使用 Python 字符串操作将值包含到查询中是很方便的。但是这样做非常不安全,而 sqlite3 给你提供了更好的方法来做到这一点:


# Do not do this!

my_timestamp = 1

c.execute("SELECT * FROM events WHERE ts = '%s'" % my_timestamp)

# Do this instead

my_timestamp = (1,)

c.execute('SELECT * FROM events WHERE ts = ?', my_timestamp)


此外,使用Python%s(或格式或格式的字符串常量)的字符串插值对于executemany来说并不是总是可行。所以在此尝试没有什么真正意义!


请记住,这些小技巧可能会(也可能不会)给你带来好处,具体取决于特定的用例。你应该永远自己去尝试,决定是否值得这么做。


英文:remusao,译文:oschina

www.oschina.net/translate/few-tips-sqlite-perf


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/304128.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

techempower之Plaintext上7百万RPS

在Plaintext这项测试中第一阶梯的分隔线基本算是7百万RPS,Beetlex并没有到到这一阶梯停留在69X万RPS处,虽然只差那数万但在排名上让人感觉不爽。Beetlex在很多项测都微微领先aspcore,但在最基础项落下一点点的确让我感觉到不太满意,更希望Bee…

mysql 大小写 if_【已解决】Windows下 MySQL大小写敏感 解决方案及分析

Windows下 MySQL大小写敏感配置zoerywzhou163.com作者:Zhouwan2017-3-27最近在window系统下 操作Linux系统下创建的数据库,发现有些不对劲,比较了半天才发现是大小写敏感的问题造成的。网上搜索了一下,解决了这个问题,…

我对CTO的理解 CTO要有技术魅力[转载]

编者按:关于CTO这个热门职业的理解总会引发热议,下面这篇博文出自资深从业人员,观点来自实践,很尖锐也很有见地。 1)错误都是自上而下 当事情出现混乱的时候,人们总是寻求寄托于Process的制定,很多的管理者…

详解全排列算法

简介给定 {1, 2, 3, , , n},其全排列为 n! 个,这是最基础的高中组合数学知识。我们以 n4 为例,其全部排列如下图(以字典序树形式来呈现):我们很容易想到用递归来求出它的所有全排列。仔细观察上图&#xff…

VS2019 调试技巧之附加进程

C# 创建服务并附加到进程进行调试步骤一:在任务栏右键-》》点击任务管理器-》》选择服务,找到启动的进程PID或者WINR 进入cmd命令 输入 netstat -ano | find "进程端口" 找端口步骤二:VS中找到“调试”菜单,选择“…

sql同时向两个表插入数据_SQL入门-数据库和客户端的安装,表的创建和数据插入...

1、如何验证MySQL数据库安装成功按照上图操作打开SQL命令行客户端输入安装MySQL时设置的密码并按enter键,得到下图:如果有显示出来红框里的内容,就表示安装成功。红框里的内容表示的是MySQL数据库版本号。2、如何用客户端(Navicat…

在sp_executesql中使用like字句

在sp_executesql中可以执行参数化的sql,但是如果sql中有like,那么一般都要拼字符串,下面的例子把两者结合了起来,既有拼sql的灵活性,又有参数化sql的优点。 declare LikeSql nvarchar(32);--定义一个like变量&#xff…

我是怎么进入Oracle这样的大企业的?

导语:人工智能是泡沫么?AI产业的未来将何去何从?机器学习又该怎么学习?AI行业从业者又是怎么看待这个行业的呢?踏入一个行业之前最好对这个行业有个全方位的了解。本文作者饶毅,现就职于甲骨文公司。AI行业…

websocket文档_WebSocket推送 原理扫盲到上手实践

关于服务端推送技术,大家比较熟悉的可能就是轮询,但是轮询只能是由客户端先发起http请求。在HTTP1.1中的keep-alive方式建立的http连接,但是一个Request只能对应一个Response,而且这个Response是被动的,不能主动发起。…

DISCUZ7.2在通达OA2009桌面显示技巧

最近在测试DISCUZ 和通达...猛然间看到,,,可以DISCUZ可以和通达完美结合,禁不住进行了测试.....效果还挺好的...最初效果图如下:感觉挺别扭的,于是将DISCUZ调用代码更改了代码如下:[show1] <table width"100%" > <tr> <td alignleft> <di…

如何在 ASP.Net Core 中使用 Lamar

ASP.Net Core 自带了一个极简的 开箱即用 的依赖注入容器&#xff0c;实际上&#xff0c;你还可以使用第三方的 依赖注入容器 来替代它&#xff0c;依赖注入是一种设计模式&#xff0c;它能够有效的实现对象之间的解耦并有利于提高单元测试和维护性&#xff0c;你可以使用 依赖…

扎克伯格做了26张PPT,员工效率提10倍,已被疯狂传阅!

1、时间常有&#xff0c;时间在于优先。2、时间总会有的&#xff1a;每天只计划 4&#xff5e;5 小时真正的工作。3、当你在状态时&#xff0c;就多干点&#xff1b;不然就好好休息&#xff1a;有时候会连着几天不是工作状态&#xff0c;有时在工作状态时却又能天天忙活 12 小时…

2010南非世界杯32强手绘海报

2010南非世界杯32强手绘海报 2010年南非世界杯已经进入最后的倒计时&#xff0c;近日&#xff0c;ESPN推出了一组以世界杯32强为主题的手绘海报。在这组颇有漫画性质的海报中&#xff0c;32强每支球队的特点都是展现得淋淋尽致&#xff0c;卡卡、梅西、C罗、托雷斯等球星也自然…

jsp后台批量导入excel表格数据到mysql中_PHP批量导入excell表格到mysql数据库

PHP批量导入excell表格到mysql数据库,本人通过亲自测试&#xff0c;在这里分享给大家1&#xff0c;下载 php excell类库网上搜索可以下载&#xff0c;这里不写地址2&#xff0c;建html文件请选择你要上传的EXCELL:excell下载模板请选择你要上传的excell:3,php代码写入//批量上…

鹅厂二面,Nginx回忆录

上周二面鹅厂&#xff0c;面试官问出了“nginx你了解吗&#xff1f;”这样宽泛直白的句式&#xff0c;我一时抓不到重点&#xff0c;一时语噻。下班想了一下&#xff0c;平时潜移默化用到不少nginx的能力&#xff0c;但在面试的时候没有吹成对应的概念。面谈nginx核心能力nginx…

nagios监控mysql主机,nginx,cpu,网卡流量

nagios安装完成&#xff0c;打开/usr/local/nagios/etc/nagios.cfg去掉cfg_dir/usr/local/nagios/etc/servers前面的#号&#xff0c;并创建/usr/local/nagios/etc/servers目录&#xff08;此目录下放被监控机的配置文件&#xff09;&#xff0c;重启nagios服务service nagios r…

干货|吴恩达Coursera课程教你学习神经网络二!

上一周的课程中讲了神经网络的结构以及正向传播(feed forward)过程&#xff0c;了解了神经网络是如何进行预测的&#xff0c;但是预测的结果怎么和真是结果进行比较以及发现了错误如何修改还没有提及。这一周的课程中&#xff0c;介绍了cost function作为结果比较的标准以及bac…

vue预加载动态生成runtime.js_预渲染 prerender-spa-plugin 避坑指南

预渲染原理在webpack打包结束并生成文件后&#xff08;after-emit hook&#xff09;&#xff0c;会启动一个server模拟网站的运行&#xff0c;用puppeteer&#xff08;google官方的headless 无头浏览器浏览器&#xff09;访问指定的页面route&#xff0c;得到相应的html结构&am…

Dotnet的数据定位和匹配

Dotnet里&#xff0c;数据定位和匹配的相关编程现在变得很舒服。最近项目紧&#xff0c;还要不停出差。所以&#xff0c;写个短点的、最近经常用到的内容&#xff1a;数据定位和匹配。数据定位假设我们有这样一个数组&#xff1a;var array new int[] { 1, 2, 3, 4, 5, 6, 7, …

一年后,我又来了

差不多一年没有更新过博客了&#xff0c;这一年&#xff0c;怀孕生子&#xff0c;人变懒惰了&#xff0c;不想思考。在家休假也大半年了&#xff0c;颓废&#xff0c;什么也没干。现在宝宝已经两个多月了&#xff0c;没多久也要上班了&#xff0c;生活也逐渐走上正轨&#xff0…