如何将 SQLite 数据库的大小限制增加到 140TB?

How to increase the size limit of a SQLite database to 140TB?

我正在 Java 中写入 SQLite 数据库。几天来一切顺利,然后突然一切都崩溃了,我得到了以下堆栈跟踪:

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 的内容(包含数据库):

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

我已经在多台服务器上 运行 尝试过代码,但我总是得到同样的结果。数据库中的一个 table 中可能有大约 10 亿行,另一个中大约有 2 亿行。根据 SQLite's Limit page,我离 "The theoretical maximum number of rows in a table is 2^64," 很远,最大数据库大小是 "the maximum size of a database file is 2147483646 pages. At the maximum page size of 65536 bytes, this translates into a maximum database size of approximately 1.4e+14 bytes (140 terabytes...)",我也离它很远。

阅读以上内容,我的解释是,如果我将 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();
        }
    }

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

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

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

您应该在创建数据库之前设置页面大小,之后执行 PRAGMA page_size. For an existing database, you'd have to run VACUUM,这不是您想要处理大量数据的事情。


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