2017-09-02 5 views
0

私はJavaでSQLite DBに書いています。すべては数日のためによく行っていた、その後、突然、すべてが墜落したと私は、次のスタックトレースました:ディスクがいっぱいでない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 

はここ(デシベルを含む)の/出力内容です:

[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 

私は、複数のサーバー上でコードを実行しようとしました、と私は同じことを得続けますもの。データベースの1つのテーブルにはおそらく約10億行があり、もう1つのテーブルには2億もの行があります。 SQLite's Limit pageによれば、「テーブル内の理論上の最大行数は2^64です。私はどこにもいません。データベースの最大サイズは2147483646ページです。最大ページ65536バイトのサイズで、これはおよそ1.4e + 14バイト(140テラバイト)の最大データベースサイズに変換されます。

上記を読めば、page_sizeを65536に増やすと、140TBの最大値に達することができます。しかし、これはパフォーマンスに重大な影響を与える可能性があることも読んでいます。これは、140TBを達成する正しい方法ですか?そうでない場合は、サイズ制限を140TBに増やすための手順は何ですか?どのようにすれば、パフォーマンスにどのように影響しますか?

EDIT

クエリを追加:

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

最大データベースサイズを大きくするのみ方法は、ページサイズを大きくすることです。

巨大なデータベースの場合、1ページあたりのオーバーヘッドを減らすため、ページサイズをできるだけ大きくすることが改善されています。

通常のデータベースであっても、ページサイズはファイルシステムで使用されているブロックサイズ以上でなければなりません。現在は4KBです。 (最近のSQLiteバージョンではこれが自動的に行われますが、データベースのページサイズは512バイトです)

PRAGMA page_sizeを実行してデータベースを作成する前に、ページサイズを設定する必要があります。既存のデータベースの場合は、あとでVACUUMを実行する必要があります。これは、大量のデータを扱う場合とは異なります。


REPLACEは、古い行が存在する場合は常に削除することに注意してください。これらのほとんどが行を実際に変更しない場合は、2つのステートメントでこれを行うことで、多くのI/Oを回避できます。

+0

ええ、VACUUMは本当にテーブルのこの大規模なオプションではないことが判明しました。大規模なデータベースを起動した後は、大規模なデータベースのサイズを変更する方法は実際にはないようです。 REPLACEに関するヒントをありがとう!それは私のコードを少し削除するコードをスピードアップしました。 –

関連する問題