小。速度很快。可靠。
选择任意三个选项。
SQLite使用的临时文件

1介绍

其中一个独特的特征属于SQLite是指一个数据库由一个磁盘文件组成。这简化了SQLite的使用,因为移动或备份数据库很简单,只需复制一个文件。它还使SQLite适合用作应用程序文件格式.但是,虽然完整的数据库保存在单个磁盘文件中,SQLite在处理数据库的过程。

本文描述SQLite的各种临时文件创建和使用。它描述了创建文件的时间、它们被删除了,它们用于什么,为什么重要,以及如何在创建临时文件的系统上避免这些错误价格昂贵。

不考虑SQLite使用临时文件的方式SQLite与应用程序签订的合同的一部分。这个本文档中的信息正确描述了如何SQLite在编写本文档时或最后一次运行已更新。但不能保证SQLite的未来版本将以相同的方式使用临时文件。新型临时可能会使用文件,并且当前的临时文件使用可能会停止SQLite的未来版本中。

2九种临时文件

SQLite当前使用九种不同类型的临时文件:

  1. 回滚日记帐
  2. 超级期刊
  3. 写入头日志(WAL)文件
  4. 共享内存文件
  5. 报表日记帐
  6. TEMP数据库
  7. 视图和子查询的具体化
  8. 瞬态指数
  9. VACUUM使用的瞬态数据库

有关每个临时文件类型的其他信息在续集中。

2.1.回滚日志

回滚日志是用于实现SQLite中的原子提交和回滚功能。(有关如何工作的详细讨论,请参阅标题为SQLite中的原子提交.)回滚日志始终位于同一目录中作为数据库文件,并且与数据库同名文件,8个字符除外“-日记账”追加。回滚日志通常是在事务首先启动,通常在事务处理时删除提交或回滚。回滚日志文件对于实现SQLite的原子提交和回滚功能。没有回滚日志,SQLite将无法回滚交易不完整,以及是否发生崩溃或断电在事务处理过程中,整个数据库可能在没有回滚日志的情况下损坏。

回滚日志是通常事务的开始和结束。但也有例外遵守这条规则。

如果在交易过程中发生崩溃或断电,然后回滚日志文件留在磁盘上。下一次另一个应用程序试图打开数据库文件,它注意到废弃的回滚日志的存在(我们称之为“hot”日志”)并使用日志将数据库还原到启动前的状态不完整事务的。SQLite就是这样实现的原子提交。

如果应用程序将SQLite放入独占锁定模式使用杂注:

PRAGMA锁定模式=独家;

SQLite在第一个日志开始时创建一个新的回滚日志独占锁定模式会话中的事务。但在事务结束时,它不会删除回滚日记账。回滚日志可能被截断,或其标头可能为零(取决于您使用的SQLite版本)但不会删除回滚日志。回滚日志是在退出独占访问模式之前不会删除。

回滚日志创建和删除也由日志模式杂注.默认日志模式是DELETE,这是默认行为在每个事务结束时删除回滚日志文件,如上所述。PERSIST日志模式放弃删除日志文件,并重写回滚日志头使用零,防止其他进程回滚日志,因此具有与删除日志文件相同的效果而不需要从磁盘中实际删除文件。在其他文字,日志模式PERSIST表现出与所见相同的行为处于EXCLUSIVE锁定模式。这个OFF日志模式导致SQLite完全忽略回滚日志。换句话说,如果日志模式为设置为OFF。OFF日志模式禁用原子SQLite的提交和回滚功能。ROLLBACK命令设置为OFF日志模式时不可用。如果发生碰撞或电源故障损失发生在使用OFF日记帐的交易的中间模式下,无法恢复,数据库文件可能腐败。MEMORY日志模式使回滚日志存储在内存而不是磁盘。ROLLBACK命令在以下情况下仍然有效日志模式为MEMORY,但因为的磁盘上不存在文件恢复、崩溃或在使用MEMORY日志模式可能会导致数据库损坏。

2.2.预写日志(WAL)文件

使用预写日志或WAL文件代替回滚日志当SQLite在WAL模式。与回滚日志一样,WAL文件的目的是实现原子提交和回滚。WAL文件始终位于同一目录中作为数据库文件,并且与数据库同名文件,4个字符除外“-沃尔”追加。当第一次连接到数据库被打开,通常在最后一次与数据库的连接关闭。然而,如果最后一次连接如果没有完全关闭,WAL文件将保留在文件系统中并且将在下次数据库被清除时自动清除开的。

2.3.共享内存文件

在中操作时WAL模式,所有关联的SQLite数据库连接对于相同的数据库文件,需要共享一些用作WAL文件的索引。在大多数实现中,此共享内存是通过对专门为此目的创建的文件调用mmap()实现:共享内存文件。共享内存文件(如果存在)位于位于与数据库文件相同的目录中,并且与数据库文件,4个字符除外“-shm公司”追加。共享内存文件仅在WAL模式下运行时存在。

共享内存文件不包含永久性内容。唯一的目的共享内存文件的作用是提供一块共享内存供使用由多个进程以WAL模式访问同一数据库。如果变频调速器能够为访问共享内存,则可以使用替代方法,而不是共享内存文件。例如,如果PRAGMA锁定模式设置为EXCLUSIVE(意味着只有一个进程能够访问数据库文件),则共享内存将从堆中分配,而不是从外分配而共享内存文件将永远不会创建。

共享内存文件与其关联的WAL文件具有相同的生存期。共享内存文件是在创建WAL文件时创建的删除WAL文件时删除。在WAL文件恢复期间共享内存文件是基于正在恢复的WAL文件。

2.4.超级日志文件

超级日志文件用作原子提交的一部分单个事务更改为多个事务时的流程已添加到单个数据库连接使用附件声明。超级日志文件总是与主数据库文件位于同一目录中(主数据库文件是标识的数据库在原件中sqlite3_open(),sqlite3_open16(),或sqlite3_open_v2()创建了数据库连接)带有随机后缀。超级日志文件包含所有附加的各种辅助数据库的名称在交易期间发生了更改。多数据库删除超级日志文件时提交事务。请参阅标题为SQLite中的原子提交对于其他细节。

如果没有超级日志,事务将在多数据库上提交每个数据库的事务都是原子的,但它并非所有数据库都是原子的。换句话说,如果commit在中间被崩溃或断电中断,然后对其中一个数据库的更改可能会在更改期间完成到另一个数据库可能会回滚。超级日志导致所有将所有数据库中的更改一起回滚或提交。

超级日志文件仅为创建承诺操作涉及多个数据库文件,其中至少有两个数据库满足以下所有要求:

  1. 数据库被事务修改
  2. 这个PRAGMA同步设置未关闭
  3. 这个PRAGMA日志_模式不是OFF、MEMORY或WAL

这意味着SQLite事务不是原子的在断电时跨多个数据库文件文件已关闭同步或正在使用日志OFF、MEMORY或WAL模式。对于同步OFF和journal_modes OFF和MEMORY,如果事务提交被断电中断。对于WAL模式,单个数据库文件自动更新通过断电,但在多文件事务的情况下,某些文件可能会回滚,而其他文件可能会前滚电力恢复。

2.5.报表日志文件

语句日志文件用于回滚的部分结果较大事务中的单个语句。例如,假设UPDATE语句将尝试修改数据库中的100行。但在修改前50行后,UPDATE点击应阻止整个语句的约束冲突。报表日记帐用于撤消前50行更改使数据库恢复到开始时的状态声明的。

仅为UPDATE或INSERT语句创建语句日志这可能会更改数据库的多行,并且可能会约束或触发器中的RAISE异常,因此需要撤消部分结果。如果UPDATE或INSERT不包含在BEGIN中。。。承诺,如果那么,同一数据库连接上没有其他活动语句自普通可以改用回滚日志。如果有其他选择,也会省略报表日记帐冲突解决算法已使用。例如:

更新或失败。。。更新或忽略。。。更新或替换。。。更新或回滚。。。插入或失败。。。插入或忽略。。。插入或替换。。。插入或回滚。。。替换为。。。。

报表日记帐是随机命名的,不一定与主数据库位于同一目录中,并自动交易结束时删除。的大小报表日记帐与实施的更改的大小成比例由导致语句日志的UPDATE或INSERT语句执行待创建。

2.6.TEMP数据库

使用“CREATE TEMP TABLE”语法创建的表仅对可见数据库连接其中“创建温度表”语句最初被求值。这些TEMP表一起与任何相关联的索引、触发器和视图一起存储在单独的临时数据库文件中,该文件创建为只要看到第一条“CREATE TEMP TABLE”语句。此单独的临时数据库文件还具有关联的回滚日志。删除了用于存储TEMP表的临时数据库文件数据库连接已关闭使用sqlite3_close().

TEMP数据库文件与辅助数据库非常相似使用添加的文件附件声明,尽管有一些特殊属性。数据库连接已关闭。TEMP数据库始终使用同步=关闭日志模式=PERSISTPRAGMA设置。并且,TEMP数据库不能与DETACH公司也不能另一个过程连接TEMP数据库。

与TEMP数据库关联的临时文件及其只有在应用程序使用时才创建回滚日志“CREATE TEMP TABLE”语句的。

2.7.视图和子查询的具体化

包含子查询的查询有时必须求值子查询分开并将结果存储在临时表,然后使用临时表的内容进行计算外部查询。我们称之为“物化”子查询。SQLite中的查询优化器试图避免具体化,但有时这是不容易避免的。每个由物化创建的临时表都被存储在自己的单独临时文件中,该文件将自动在查询结束时删除。这些临时表的大小取决于当然,数据在子查询的物化中。

IN运算符右侧的子查询必须经常被具体化。例如:

SELECT*FROM ex1 WHERE ex1.a IN(SELECT b FROM ex2);

在上面的查询中,计算子查询“SELECT b FROM ex2”其结果存储在一个临时表中(实际上是一个临时index),其允许确定值ex2.b使用简单的二进制搜索存在。构建此表后,运行外部查询,并对每个预期结果行进行检查用于查看临时表中是否包含ex1.a。只有当检查为true时,才会输出该行。

为了避免创建临时表,可以重写查询如下:

从ex1 WHERE EXISTS中选择*(从ex2 WHERE ex2.b=ex1.a中选择1);

SQLite的最新版本(版本3.5.42007-12-14)及更高版本)会自动重写如果列ex2.b上存在索引。

如果IN运算符的右侧可以是值列表如下所示:

从ex1中选择*IN(1,2,3);

IN右侧的列表值被视为必须物化的子查询。换句话说前面的语句表现为:

SELECT*FROM ex1 WHERE a IN(选择1 UNION ALL)选择2 UNION ALL选择3);

临时索引始终用于保存IN运算符的右侧是值的列表。

子查询出现时可能还需要具体化在SELECT语句的FROM子句中。例如:

选择*FROM ex1 JOIN(从ex2选择b)AS t ON t.b=ex1.a;

根据查询,SQLite可能需要具体化“(SELECT b FROM ex2)”子查询到临时表中,然后执行ex1和临时表之间的联接。这个查询优化器试图通过“展平”查询。在上一个示例中,可以将查询展平,SQLite将自动将查询转换为

选择ex1.*,ex2.b FROM ex1 JOIN ex2 ON ex2.b=ex1.a;

更复杂的查询可能无法使用查询扁平化以避免临时表。是否查询是否可以扁平化取决于以下因素子查询或外部查询是否包含聚合函数,ORDER BY或GROUP BY子句、LIMIT子句等。查询何时可以展平和何时不能展平的规则如下非常复杂,超出了本文件的范围。

2.8.瞬态指标

SQLite可以利用瞬态指数实现SQL语言功能,如:

每个瞬态索引都存储在其自己的临时文件中。临时索引的临时文件将自动删除在使用它的语句的末尾。

SQLite努力使用预先存在的索引。如果已经存在适当的索引,SQLite将遍历用于提取请求的信息,从而使行在所需的顺序。但是如果SQLite找不到合适的索引它将计算查询并将每一行存储在一个瞬态索引中其数据是行数据,其键是ORDER BY术语。计算完查询后,SQLite返回并遍历从开始到结束的瞬态索引,以便输出按所需顺序排列。

SQLite通过对按GROUP by条款建议的顺序。每个输出行是与前一个进行比较,看看它是否启动了一个新的“组”。按GROUP by术语排序的方式完全相同按ORDER by条款订购。使用预先存在的索引如果可能,但如果没有合适的索引可用创建索引。

聚合查询上的DISTINCT关键字由实现在临时文件中创建临时索引并存储该索引中的每个结果行。当计算新的结果行时检查它们是否已经存在于瞬态中索引,如果他们这样做,新的结果行将被丢弃。

用于复合查询的UNION操作符是通过创建临时文件中的临时索引并存储结果临时索引中的左右子查询的,丢弃重复。计算完这两个子查询后瞬态索引从头到尾遍历以生成最终输出。

复合查询的EXCEPT运算符通过创建临时文件中的临时索引,存储在此瞬态索引中保留子查询,然后删除结果从transient索引的右子查询,最后遍历索引从头到尾获得最终输出。

用于复合查询的INTERSECT运算符由实现创建两个单独的瞬态索引,每个索引在一个单独的临时文件。计算左侧和右侧子查询每一个都成为一个单独的瞬态指数。然后是两个指数一起浏览,并在两个索引中显示条目输出。

注意,用于复合查询的UNION ALL操作符没有使用瞬态指数本身(当然是正确的UNION ALL的左子查询可能使用瞬态索引取决于它们的构成方式。)

2.9.使用的瞬态数据库真空

这个真空命令通过创建临时文件来工作然后将整个数据库重建为临时数据库文件。然后将临时文件的内容复制回到原始数据库文件中,临时文件为删除。

由创建的临时文件真空命令仅存在在命令本身的持续时间内。临时的大小文件将不大于原始数据库。

三。SQLITE_TEMP_STORE编译时参数和Pragma

与事务控制关联的临时文件,即回滚日志、超级日志、预写日志(WAL)文件,和共享内存文件始终写入磁盘。但其他类型的临时文件可能存储在内存中仅写入磁盘,从未写入磁盘。无论是否为回滚以外的临时文件,super和语句日志被写入磁盘或仅存储在内存中取决于SQLITE_TEMP_STORE数据库编译时参数临时存储杂注,以及临时文件的大小。

这个SQLITE_TEMP_STORE数据库compile-time参数是一个#define,其值为介于0和3之间的整数,包括0和3。的含义SQLITE_TEMP_STORE存储编译时间参数如下:

  1. 无论设置如何,临时文件始终存储在磁盘上临时存储杂注.
  2. 默认情况下,临时文件存储在磁盘上,但可以临时存储杂注.
  3. 默认情况下,临时文件存储在内存中,但这可以是临时存储杂注.
  4. 无论设置如何,临时文件始终存储在内存中临时存储杂注.

的默认值SQLITE_TEMP_STORE数据库编译时参数为1,这意味着在磁盘上存储临时文件,但提供选项使用临时存储杂注.

这个临时存储杂注也影响存储位置决定的整数值临时文件。temp_store杂注的值具有以下含义:

  1. 将磁盘或内存存储用于确定的临时文件SQLITE_TEMP_STORE数据库编译时参数。
  2. 如果SQLITE_TEMP_STORE存储compile-time参数指定的内存存储临时文件,然后覆盖该决定并使用磁盘存储。否则,请遵循SQLITE_TEMP_STORE数据库编译时间参数。
  3. 如果SQLITE_TEMP_STORE存储compile-time参数指定的磁盘存储临时文件,然后覆盖该决定并使用内存存储。否则,请遵循SQLITE_TEMP_STORE数据库编译时间参数。

默认设置临时存储杂注为0,这意味着遵循SQLITE_TEMP_STORE数据库编译时间参数。

重申一下SQLITE_TEMP_STORE存储编译时参数和临时存储杂注只有影响回滚日志以外的临时文件和超级杂志。回滚日志和超级日志始终写入磁盘,而不管这个SQLITE_TEMP_STORE数据库编译时参数和临时存储杂注.

4其他临时文件优化

SQLite使用最近读写数据库的页面缓存页。此页面缓存不仅用于主数据库文件,但也用于临时存储的瞬态索引和表文件夹。如果SQLite需要使用临时索引或表,并且这个SQLITE_TEMP_STORE数据库编译时参数和临时存储杂注设置为在磁盘上存储临时表和索引最初仍存储在页面缓存的内存中。这个临时文件未打开,信息不真实写入磁盘,直到页面缓存已满。

这意味着在许多常见情况下,临时表并且索引很小(小到可以放入页面缓存)不会创建临时文件,也不会发生磁盘I/O。仅限当临时数据变得太大而无法放入RAM时信息泄露到磁盘上。

每个临时表和索引都有自己的页面缓存其可以存储所确定的数据库页面的最大数量由SQLITE_DEFAULT_TEMP_CACHE_SIZE编译时参数决定。(默认值为500页。)页面缓存中的最大数据库页面数为每个临时表和索引都是相同的。该值不能在运行时或按表或按index进行更改。每个临时文件都通过其拥有SQLITE_DEFAULT_TEMP_CACHE_SIZE页面限制。

5临时文件存储位置

创建临时文件的目录或文件夹为由特定于OS的变频调速器.

在类unix系统上,按以下顺序搜索目录:

  1. 由设置的目录PRAGMA temp_store_directory(PRAGMA临时存储目录)或通过sqlite3_temp_directory(sqlite3_模板目录)全局变量
  2. SQLITE_TMPDIR环境变量
  3. TMPDIR环境变量
  4. /var/tmp
  5. /用户/tmp
  6. /临时
  7. 当前工作目录(“.”)
发现上述第一个存在并具有写入和使用执行位集。最后的“.”回退对某些人来说很重要在chroot监狱中使用SQLite的应用程序可用的标准临时文件位置。

在Windows系统上,按以下顺序搜索文件夹:

  1. 由设置的文件夹PRAGMA temp_store_directory(PRAGMA临时存储目录)或通过sqlite3_temp_directory(sqlite3_模板目录)全局变量
  2. GetTempPath()系统接口返回的文件夹。
SQLite本身并不关注环境变量在这种情况下,尽管GetTempPath()系统调用可能会这样做。CYGWIN版本的搜索算法不同。检查详细信息的源代码。

此页面上次修改时间2022-01-08 05:02:57联合技术公司