【问题标题】:Query that returns the size of a table in a SQLite database返回 SQLite 数据库中表大小的查询
【发布时间】:2022-03-13 14:41:22
【问题描述】:

我有一个包含许多表的 SQLite 数据库。我们正在编写一个维护工具,该工具将从表中删除“陈旧”数据,直到该表的大小达到整个数据库文件的某个百分比或更小。

我知道如何确定数据库文件的大小——我通过执行来做到这一点

PRAGMA PAGE_SIZE;

PRAGMA PAGE_COUNT;

在两个单独的查询中并将两者相乘以获得文件大小(以字节为单位)。是的,我知道我可以只获取文件的大小(以字节为单位),但这类似于我在其他数据库中所做的方式,我想坚持下去,至少现在是这样。

我的问题是我不知道如何获取 TABLE 的大小。必须有某种方法来做到这一点。谁能指出我正确的方向?

【问题讨论】:

  • 我不知道查询,但请查看sqlite.org/download.html 上的 sql_analize 工具,./sqlite3_analyze path_to_db/database.sqlite > dbinfo.sql 将为您提供有关磁盘上每个表大小的详细信息。
  • (如果是出于清理目的,删除记录后别忘了VACUUM;
  • 感谢您的提醒
  • 您可以根据存储在该特定表中的记录数来触发操作,而不是查看表大小。您可以轻松获得的记录数。
  • @NewStackUser:谢谢你的建议。

标签: database sqlite


【解决方案1】:

如果SQLite是用SQLITE_ENABLE_DBSTAT_VTAB编译的,可以查询dbstat表。这应该返回表TABLENAME 的表大小(以字节为单位):

SELECT SUM("pgsize") FROM "dbstat" WHERE name='TABLENAME';

https://www.sqlite.org/dbstat.html

这是sqlite3_anazlyer CLI 工具所使用的,也可以用于此目的。

【讨论】:

  • 有趣。 SQLite 是否默认使用SQLITE_ENABLE_DBSTAT_VTAB 编译?我相信大多数人只使用 NuGet 安装的 DLL。
  • 我没有尝试过 NuGet DLL,但我相信它通常不会以这种方式编译。我尝试了 PHP 的 SQLite3 PDO 驱动程序并没有启用它。
  • 这适用于从 Ubuntu 19.10 存储库包安装的 SQLite。 :-)
  • 这对我不起作用。顺便说一句,您可以检查 PRAGMA compile_options 使用了哪些编译选项以及有关默认选项 here 的信息,
  • @ashleedawg 你怎么了?即使启用了SQLITE_ENABLE_DBSTAT_VTAB,它是否也会产生错误?还是会导致错误的结果?您是否尝试过 SELECT * FROM "dbstat" 来检查表 dbstat 包含的内容?
【解决方案2】:

您可以为此使用sqlite3_analyzer tool,它可以是downloaded here。只需在您的数据库上运行它,它就会吐出很多有趣的统计数据,而且还可以直接通过管道传输到另一个 SQLite 数据库:

$ sqlite3_analyzer my_db.sqlite

【讨论】:

    【解决方案3】:

    没有简单的方法可以查询表的大小。所以我最终做的是通过将行数乘以行大小的估计值来估计表的大小。我手动求和整数列的长度(每个 4 个字节),加上长列的长度总和(每个 8 个字节),再加上使用查询的字符串列的平均长度估计值。像这样的:

    SELECT COUNT(*) *  -- The number of rows in the table
         ( 24 +        -- The length of all 4 byte int columns
           12 +        -- The length of all 8 byte int columns
           128 )       -- The estimate of the average length of all string columns
    FROM MyTable
    

    唯一的问题是:

    • 它会高估任何具有整数或长列的行的大小,该列可以为空,而这恰好为空
    • 它会高估或低估字符串列的长度。
    • 它不考虑索引的大小。

    这对于我们的实施来说已经足够了。您可以通过更复杂的查询来更好地计算表的大小,该查询将空值和字符串列的实际长度考虑在内。

    【讨论】:

    • 这应该如何工作?我总是只将列乘以 164(即 24+12+128)
    • COUNT(*) 函数返回符合条件的行数。其余数字确实是等于 164 的常数。它不会返回行的实际大小,只是估计表占用了多少空间。
    • 你不能选择字段类型,所以你做一个可重用的函数吗?
    • SQLite 的问题在于,您无法根据表定义中指定的类型来判断行的列中存储了什么。它更多地取决于您用于将数据写入表的代码。我没有时间也没有必要走那么远,所以我只是整理了一些对我有用的东西。我不再从事那份工作,也不必再使用 SQLite,所以如果你想试一试,那就去吧。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-19
    • 2017-12-07
    • 2016-11-01
    • 1970-01-01
    • 2020-08-28
    • 2019-08-24
    相关资源
    最近更新 更多