CSVファイルからSQLite DBに値を解析しようとしていますが、ファイルはかなり大きいです(2,500,000行)。私はプログラムを数時間走らせて、どこまで印刷したのですが、私の計算では、ファイルは完全に解析するのに約100時間かかってしまいました。CSVファイルから大量のデータをJavaのSQLite DBに効率的に追加する
私は、このプログラムをバックグラウンドプロセスとして、少なくとも1週間に1回、前回とほぼ同じ90%の新しいCSVファイルで実行する必要があります。私は自分のプログラムを改善するためのいくつかの解決策を思いついた。しかし、私はデータベースについてよく知らないので、それぞれのソリューションについて質問があります。
私がすでに持っているものよりも効率的にCSVファイルを読む方法はありますか?
ObjectOutputStreamをインスタンス化し、それをBLOBとして非常に計算コストがかかりますか?代わりに値を直接追加することもできますが、BLOBを後で使用するので、新しい値を複数回インスタンス化できなくなります。
接続プーリング、または他の方法でConnectionを使用する方法を変更する方が効率的ですか?
私はINSERT OR IGNOREを使用することができるようにURL列を設定していますが、これを小さなデータセット(〜10000行)でテストすると、テーブルを削除して再投入する場合に比べてパフォーマンスが向上しません。一意の値だけを追加する方が速いのですか?
私が作っている間違いはありますか?あなたのコードで最大のbottleckは、あなたが挿入操作をバッチ処理されていないことである
public class Database{ public void createResultsTable(){ Statement stmt; String sql = "CREATE TABLE results(" + "ID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, " + "TITLE TEXT NOT NULL, " + "URL TEXT NOT NULL UNIQUE, " ... ... + "SELLER TEXT NOT NULL, " + "BEAN BLOB);"; try { stmt = c.createStatement(); stmt.executeUpdate(sql); } catch (SQLException e) { e.printStackTrace();} } public void addCSVToDatabase(Connection conn, String src){ BufferedReader reader = null; DBEntryBean b; String[] vals; try{ reader = new BufferedReader(new InputStreamReader(new FileInputStream(src), "UTF-8")); for(String line; (line = reader.readLine()) != null;){ //Each line takes the form: "title|URL|...|...|SELLER" vals = line.split("|"); b = new DBEntryBean(); b.setTitle(vals[0]); b.setURL(vals[1]); ... ... b.setSeller(vals[n]); insert(conn, b); } } catch(){ } } public void insert(Connection conn, DBEntryBean b){ PreparedStatement pstmt = null; String sql = "INSERT OR IGNORE INTO results(" + "TITLE, " + "URL, " ... ... + "SELLER, " + "BEAN" + ");"; try { pstmt = c.prepareStatement(sql); pstmt.setString(Constants.DB_COL_TITLE, b.getTitle()); pstmt.setString(Constants.DB_COL_URL, b.getURL()); ... ... pstmt.setString(Constants.DB_COL_SELLER, b.getSeller()); // ByteArrayOutputStream baos = new ByteArrayOutputStream(); // oos = new ObjectOutputStream(baos); // oos.writeObject(b); // byte[] bytes = baos.toByteArray(); // pstmt.setBytes(Constants.DB_COL_BEAN, bytes); pstmt.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } finally{ if(pstmt != null){ try{ pstmt.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
ファイルの各行で新しいprepared statementを作成したくないのが理想的です。あなたはそれを再利用したい。 – 4castle
あなたのコードは現在動作しているようですが、あなたはそれを改善しようとしています。一般的に、これらの質問はこのサイトでは強すぎますが、[CodeReview.SE](// codereview.stackexchange.com/tour)のほうが良いかもしれません。このサイトよりも少し厳密であるため、[必要条件](// codereview.stackexchange.com/help/on-topic)を必ずお読みください。 – 4castle
@ 4castleありがとうございます。 PreparedStatementをループから外して1000行でテストし、約3秒の改善が得られました。だからそれはスタートです。 – Sam