2017-09-02 72 views
0

我正在寫Java到SQLite數據庫。一切進展順利幾天,然後突然一切都崩潰了,我得到了以下堆棧跟蹤:如何將SQLite數據庫的大小限制增加到140TB?

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輸出:

[email protected]:/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 

這裏的/輸出的內容(包含DB):

[email protected]:/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太字節......)「,我也遠不及。

閱讀以上內容,我的解釋是,如果我將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(); 
     } 
    } 
+0

什麼是您正在運行的查詢生成此異常?您可能會遇到SQLite在查詢執行期間必須生成臨時表的問題,這涉及到在磁盤上生成臨時文件。如果您的查詢足夠大,則可能會生成足夠大的文件以導致空間不足問題。 – birryree

+0

我檢查過了,我運行的最後一臺服務器有一個2TB的系統驅動器,幾乎所有的驅動器都是免費的,而且還是同樣的問題。我更新了問題並添加了查詢。 –

回答

1

增加最大數據庫大小的唯一方法是增加頁面大小。

對於大型數據庫,使頁面尺寸儘可能大是一種改進,因爲可以減少每頁的開銷。

即使對於普通數據庫,頁面大小也應該至少與文件系統使用的塊大小一樣大,現在是4 KB。 (最近的SQLite版本會自動執行此操作,但您的數據庫的頁面大小爲512字節。)

您應該在創建數據庫之前通過執行PRAGMA page_size來設置頁面大小。對於現有的數據庫,之後必須運行VACUUM,這不是您想要處理大量數據的問題。


請注意,REPLACE總是刪除舊行,如果它存在;如果其中大多數實際上並沒有改變行,那麼可以通過使用兩條語句來避免太多的I/O。

+0

是的,事實證明VACUUM並不是真正的選擇。看起來好像沒有可行的方法來調整大型數據庫的大小,一旦你啓動它。感謝關於REPLACE的提示!它加快了我的代碼代碼刪除了一些。 –