Sqlite 数据量不大,但是数据库文件比较大
如果你的 SQLite 数据库文件很大,但是数据库里面存储的数据很少,可能是因为 SQLite 的特性所导致的。
SQLite 是一种嵌入式数据库,它的设计目标是在嵌入式设备上提供一个轻量级的、自包含的数据库引擎。由于它的设计目标,SQLite 的数据存储方式与其他数据库不同,它主要采用了以下特性:
- 数据库文件预分配空间
当你创建一个 SQLite 数据库时,SQLite 会为该数据库文件预分配一定的空间。这个空间是在磁盘上分配的,但是并不会被实际使用。这是为了提高 SQLite 的写入性能,因为这样可以避免写入新数据时频繁地增加文件大小。
- 数据库文件不会立即缩小
当你从 SQLite 数据库中删除数据时,它并不会立即释放磁盘空间。这是因为 SQLite 需要保留已经分配的空间,以便在以后写入更多的数据时可以直接使用这些空间,而不必重新分配空间。
- 数据库文件中包含很多元数据
SQLite 数据库文件中包含很多元数据,例如表结构、索引、视图等等。这些元数据虽然不占用很多空间,但是对于数据库文件大小的影响是不可忽略的。
因此,如果你的 SQLite 数据库文件很大,但是数据库里面存储的数据很少,可能是因为上述特性所导致的。如果你想减小 SQLite 数据库文件的大小,可以尝试使用 VACUUM 命令来释放未使用的空间,或者重新创建一个新的数据库文件并将数据导入其中。
怎么使用VACUUM释放未使用的空间
使用 VACUUM 命令可以释放 SQLite 数据库文件中未使用的空间,以下是使用 VACUUM 命令的步骤:
- 打开 SQLite 数据库
首先,需要使用 SQLite 的命令行工具或者 SQLite API 打开 SQLite 数据库。如果你使用的是命令行工具,可以使用以下命令:
sqlite3 /path/to/database
其中,/path/to/database 是你的数据库文件路径。
sqlite3 命令行工具安装 sudo apt-get install sqlite3
- 进入 SQLite 命令行模式
打开 SQLite 数据库后,你需要进入 SQLite 的命令行模式。如果你使用的是命令行工具,可以直接在终端中输入 sqlite3 命令,然后按下回车键。
- 执行 VACUUM 命令
在 SQLite 命令行模式下,输入以下命令即可执行 VACUUM 命令:
VACUUM;
执行完 VACUUM 命令后,SQLite 数据库文件中未使用的空间就会被释放,数据库文件的大小也会相应地减小。
注意事项:
- VACUUM 命令可能需要一些时间才能完成,具体时间取决于数据库文件的大小和硬件性能。
- 在执行 VACUUM 命令时,需要确保没有其他进程或者线程正在访问该数据库文件,否则可能会导致数据损坏或者其他问题。
- 在执行 VACUUM 命令之前,建议先备份好数据库文件以防意外发生。
使用 VACUUM数据库文件大小没有变化
如果使用 VACUUM 命令后,SQLite 数据库文件的大小没有发生变化,可能是因为以下原因之一:
- 数据库文件中存在未提交的事务
如果在执行 VACUUM 命令之前,数据库中存在未提交的事务,那么 VACUUM 命令就无法释放未使用的空间。因此,在执行 VACUUM 命令之前,需要确保所有的事务都已经提交或者回滚。
你可以使用以下命令查询是否存在未提交的事务:
PRAGMA schema_version;
如果返回的结果不为 0,那么就存在未提交的事务。你可以使用以下命令提交或者回滚事务:
COMMIT;
或者
ROLLBACK;
执行PRAGMA schema_version;之后返回684,684是指 在 SQLite 中,每个数据库都有一个 schema(模式)版本,用于跟踪数据库结构的更改。当你对数据库进行了结构上的更改,比如添加、删除或修改表、列、索引等,SQLite 就会自动更新 schema 版本号。 在执行 `PRAGMA schema_version;` 命令后返回 684,说明当前数据库的 schema 版本号为 684。这意味着在该数据库中进行了至少 684 次结构上的更改。 需要注意的是,schema 版本号的具体值没有特定的含义,它只是一个递增的数字,用于标识数据库结构的历史记录。每个数据库的 schema 版本号可能不同,具体取决于数据库的结构变更历史。 如果你想了解更多关于 SQLite schema 版本的信息,可以参考 SQLite 官方文档中的相关章节。
sqlite 查看有多少事务没有提交
在 SQLite 中,可以使用 PRAGMA schema_version; 命令来查询当前数据库的 schema 版本号,如果返回的结果不为 0,则说明当前存在未提交的事务。
具体来说,SQLite 在执行写操作(比如插入、更新、删除等)时,会自动开启一个事务,并在事务结束时自动提交或回滚事务。如果在执行写操作后,没有显式地提交或回滚事务,那么事务就会一直处于未提交状态,直到数据库连接被关闭或者显式地提交或回滚事务为止。
因此,如果执行 PRAGMA schema_version; 命令返回的结果不为 0,就说明当前数据库存在未提交的事务。你可以通过提交或回滚事务来解决这个问题。具体来说,可以使用以下命令提交或回滚事务:
COMMIT; -- 提交事务 ROLLBACK; -- 回滚事务
需要注意的是,提交或回滚事务会影响到数据库中所有未提交的事务,如果你不确定是否要提交或回滚事务,建议先备份数据库文件以防数据丢失。
但是执行commit时,出现 cannot commit - no transaction is active;
如果执行 COMMIT; 命令时出现 "cannot commit - no transaction is active" 错误提示,可能是因为当前不存在未提交的事务。
在 SQLite 中,只有在开启了事务后才能执行 COMMIT; 命令来提交事务。如果在执行 COMMIT; 命令之前没有显式地开启事务,或者之前已经提交或回滚了事务,就会出现 "cannot commit - no transaction is active" 错误提示。
你可以使用以下命令来检查当前是否存在未提交的事务:
SELECT * FROM sqlite_master;
如果查询结果中存在 BEGIN TRANSACTION 或 SAVEPOINT 语句,就说明当前存在未提交的事务。在这种情况下,你可以使用 COMMIT; 命令来提交事务。
如果查询结果中没有 BEGIN TRANSACTION 或 SAVEPOINT 语句,就说明当前不存在未提交的事务。在这种情况下,你可以直接执行其他 SQL 命令,或者使用 BEGIN TRANSACTION; 命令来开启一个新的事务。
需要注意的是,SQLite 默认开启了自动提交模式(autocommit mode),也就是说,如果没有显式地开启事务,每个 SQL 命令都会被当作一个独立的事务进行处理,并立即提交到数据库。因此,在使用 SQLite 时,如果不需要使用事务,可以直接执行 SQL 命令,无需显式地开启或提交事务。
- 数据库文件中存在大量的空闲页
在 SQLite 数据库文件中,空闲页是指已经被分配但是当前没有被使用的页。如果数据库文件中存在大量的空闲页,那么使用 VACUUM 命令也无法释放这些空间。
你可以使用以下命令查询数据库文件中空闲页的数量:
PRAGMA freelist_count;
如果返回的结果较大,那么就存在大量的空闲页。你可以使用以下命令来释放这些空闲页:
PRAGMA auto_vacuum = FULL;
执行以上命令后,SQLite 数据库将处于增量自动 VACUUM 模式,这将自动清除大量的空闲页。请注意,这可能需要一些时间才能完成,具体时间取决于数据库文件的大小和硬件性能。
如果以上方法都无法解决问题,可能是因为数据库文件中存在其他问题,建议重新创建一个新的数据库文件并将数据导入其中。
- 不存在未提交的事务,也不存在空闲页,可能是因为数据库中存在大量已经被删除的数据占用的空间没有被及时回收
SQLite 引擎会将已经删除的数据所占用的空间保留下来,以便后续的写入操作可以更快地完成。这些空间可以被称为 "空闲页",它们可以在 VACUUM 命令执行时被回收,从而减小数据库文件的大小。
但是,在某些场景下,SQLite 引擎并不会立即回收空闲页。例如,如果你在使用 WAL 模式(Write-Ahead Logging)时,SQLite 引擎会将空闲页保存在 WAL 文件中,以便后续的写入操作可以更快地完成。在这种情况下,即使执行了 VACUUM 命令,也无法减小数据库文件的大小。
如果你在使用 WAL 模式,可以尝试使用以下步骤来减小数据库文件的大小:
- 执行
PRAGMA journal_mode = DELETE; 命令将日志模式设置为 DELETE。这个命令会禁用 WAL 模式,并将日志文件设置为普通的回滚日志文件。需要注意的是,这个命令会删除所有已经保存在 WAL 文件中但是还没有被写入数据库文件的数据。因此,在执行这个命令之前需要先确保所有的数据已经被写入数据库文件。
- 执行
VACUUM; 命令来压缩数据库。这个命令会回收已经被删除的数据占用的空间,并重新组织数据库文件,可以减小数据库文件的大小。
需要注意的是,禁用 WAL 模式可能会影响数据库的性能和数据安全性,因此在使用前需要仔细考虑。如果你需要使用 WAL 模式,并且希望减小数据库文件的大小,可以尝试使用 SQLite 所提供的其他压缩工具,例如 sqlite3_analyzer 工具。这些工具可以分析数据库文件的结构,找出占用空间较大的对象,并对其进行压缩。
怎么使用 sqlite3_analyzer 工具对sqlite库进行压缩
SQLite3_analyzer 是一个 SQLite 自带的命令行工具,用于分析 SQLite 数据库文件的结构,找出占用空间较大的对象,从而帮助用户对数据库进行优化和压缩。下面是使用 sqlite3_analyzer 工具对 SQLite 数据库进行压缩的步骤:
- 打开终端,进入 SQLite3_analyzer 工具所在的目录,例如:
cd /usr/bin ```
- 以分析模式打开数据库文件,例如:
sqlite3_analyzer -m analyze your_database_file.db ``` 这个命令会在当前目录下生成一个名为 `your_database_file.db.out` 的分析报告文件,其中包含了数据库文件的详细结构信息和占用空间较大的对象列表。
- 分析分析报告文件,找出占用空间较大的对象,并使用 SQLite3 命令行工具对这些对象进行压缩或删除操作,例如:
sqlite3 your_database_file.db "DELETE FROM your_table WHERE your_condition;" ``` 或者:
sqlite3 your_database_file.db "VACUUM your_table;"
这些命令可以删除表中不需要的数据,或者压缩表中已经删除的数据所占用的空间。
- 重新运行分析工具,查看数据库文件的占用空间是否有所减小,例如:
sqlite3_analyzer -m analyze your_database_file.db ``` 如果分析报告中显示占用空间已经减小,说明压缩操作成功。如果分析报告中仍然显示占用空间较大,可以重复步骤 3 和步骤 4,直到达到期望的文件大小。
需要注意的是,使用 sqlite3_analyzer 工具进行数据库压缩操作需要一定的 SQL 基础知识和 SQLite 数据库的使用经验。在进行操作之前,建议先备份数据库文件,避免操作失误导致数据丢失。