让 Python 更加充分的使用 Sqlite3

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

我决定试一试sqlite3。由于只需打开与数据库的链接,这样能够增长可处理的数据量,并将应用程序的加载时间减小到零。此外,我能够经过 SQL 查询替换不少Python逻辑语句。python

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

TL;DRgithub

  1. 使用大量操做 (又名 executemany)。
  2. 你不须要使用光标 (大部分时间)。
  3. 光标可被迭代。
  4. 使用上下文管理器。
  5. 使用编译指示 (当它有意义)。
  6. 推迟索引建立。
  7. 使用占位符来插入 python 值。

1. 使用大量操做

若是你须要在数据库中一次性插入不少行,那么你真不该该使用 execute。sqlite3 模块提供了批量插入的方式:executemany。sql

而不是像这样作:数据库

你能够利用这个事实,即 executemany 接受元组的生成器做为参数:安全

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

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

  • executemany: 1.6 秒
  • execute: 2.7 秒

2. 你不须要游标

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

但大多数状况下,你根本不须要光标,你能够直接使用链接对象(本文末尾会提到)。
像execute和executemany相似的操做能够直接在链接上调用。如下是一个证实此事的示例:

 

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

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

这样一来,只要你获得足够的结果,你就能够终止查询,而且不会引发资源浪费。固然,若是事先知道你须要多少结果,能够改用LIMIT SQL语句,但Python生成器是很是方便的,可让你将数据生成与数据消耗分离。

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

即便在处理SQL事务的中间,也会发生讨厌的事情。为了不手动处理回滚或提交,你能够简单地使用链接对象做为上下文管理器。 在如下示例中,咱们建立了一个表,并错误地插入了重复的值:

 

5. 使用Pragmas

…当它真的有用时

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

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

6. 推迟索引建立

假设你须要在数据库上建立几个索引,而你须要在插入不少行的同时建立索引。把索引的建立推迟到全部行的插入以后能够致使实质性的性能改善。

7. 使用占位符插入 Python 值

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

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

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

相关文章
相关标签/搜索