【问题标题】:How to increase the size limit of a SQLite database to 140TB?如何将 SQLite 数据库的大小限制增加到 140TB?
【发布时间】:2017-09-02 05:37:33
【问题描述】:

我正在用 Java 写一个 SQLite DB。几天一切顺利,然后突然一切都崩溃了,我得到了以下堆栈跟踪:

org.sqlite.SQLiteException: [SQLITE_FULL]  Insertion failed because database is full (database or disk is full)
        at org.sqlite.core.DB.newSQLException(DB.java:909)
        at org.sqlite.core.DB.newSQLException(DB.java:921)
        at org.sqlite.core.DB.throwex(DB.java:886)
        at org.sqlite.core.DB.executeBatch(DB.java:774)
        at org.sqlite.core.CorePreparedStatement.executeBatch(CorePreparedStatement.java:79)
        at co.happy.GroupByWriteFile.run(GroupByWriteFile.java:51)
        at java.lang.Thread.run(Thread.java:748)

磁盘未满。这是df -h 的输出:

root@host:/output# df -h
Filesystem      Size  Used Avail Use% Mounted on
udev             32G     0   32G   0% /dev
tmpfs           6.3G  8.7M  6.3G   1% /run
/dev/xvda1      7.7G  1.9G  5.9G  24% /
tmpfs            32G     0   32G   0% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs            32G     0   32G   0% /sys/fs/cgroup
tmpfs           6.3G     0  6.3G   0% /run/user/1000
/dev/xvdb1      2.0T  572G  1.3T  31% /input
/dev/xvdc1      2.9T  1.1T  1.8T  37% /output

这是 /output(包含 db)的内容:

root@host:/output# ls -lrth
total 1.1T
drwx------ 2 root root  16K Aug 31 23:39 lost+found
-rw-r--r-- 1 root root 1.0T Sep  2 05:12 groupby.db

我已经尝试在多台服务器上运行代码,但我一直得到同样的结果。数据库中的一个表中可能有大约 10 亿行,而另一个表中大约有 2 亿行。根据SQLite's Limit page,“一个表中的理论最大行数是2^64”,我还差得很远,最大数据库大小是,“一个数据库文件的最大大小是2147483646页。在最大页面大小为 65536 字节,这相当于最大数据库大小约为 1.4e+14 字节(140 TB...)”,而我也远不及。

阅读以上内容,我的解释是,如果我将 page_size 增加到 65536,那么我将能够达到最大 140TB。但是,我也读到这可能会对性能产生严重影响。这是实现140TB的正确方法吗?如果没有,将大小限制增加到 140TB 的步骤是什么?如果全部影响,它会如何影响性能?

编辑

添加查询:

    PreparedStatement ps = null;
    PreparedStatement ps2 = null;
    int i = 0;
    try {
        ps = conn.prepareStatement("REPLACE INTO groupByKeys VALUES (?, ?)");
        ps2 = conn.prepareStatement("INSERT INTO groupByVals VALUES (?, ?)");

    } catch (SQLException e) {
        e.printStackTrace();
    }
    while (true) {
        try {
            DedupeInstruction d = writeQueue.take();
            ps.setString(1, d.getOutFile());
            if (d.isHasCustom()) {
                ps.setInt(2, 1);
            } else {
                ps.setInt(2, 0);
            }
            ps2.setString(1, d.getOutFile());
            ps2.setString(2, d.getLine());
            ps.addBatch();
            ps2.addBatch();
            if (i % 1000 == 0) {
                ps.executeBatch();
                ps2.executeBatch();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

【问题讨论】:

  • 您正在运行的查询是什么产生了这个异常?您可能会遇到 SQLite 在查询执行期间必须生成临时表的问题,这涉及在磁盘上生成临时文件。如果您的查询足够大,它很可能会生成一个足够大的文件,从而导致空间不足的问题。
  • 我检查了一下,我运行它的最后一台服务器有一个 2TB 系统驱动器,几乎所有驱动器都是免费的,但仍然是同样的问题,立即。我已经更新了问题并添加了查询。

标签: database performance sqlite resize


【解决方案1】:

增加最大数据库大小的唯一方法是增加页面大小。

对于大型数据库,使页面大小尽可能大是一种改进,因为您可以减少每页的开销。

即使对于普通数据库,页面大小至少应该与文件系统使用的块大小一样大,现在是 4 KB。 (最近的 SQLite 版本会自动执行此操作,但您的数据库的页面大小为 512 字节。)

您应该在创建数据库之前通过执行PRAGMA page_size 来设置页面大小。对于现有数据库,您必须在之后运行VACUUM,这不是您想要处理大量数据的事情。


请注意,REPLACE 总是删除旧行(如果存在);如果其中大多数实际上并未更改行,则可以通过使用两个语句来避免大量 I/O。

【讨论】:

  • 是的,事实证明 VACUUM 在这么大的桌子上并不是一个真正的选择。一旦启动大型数据库,似乎真的没有可行的方法来调整它的大小。感谢您提供有关更换的提示!它加快了我的代码速度,稍微消除了它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-07-10
  • 1970-01-01
  • 2023-02-15
  • 2019-02-27
  • 2016-06-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多