特にSQLServerを介して、任意のSQL SELECT クエリの非常に大きな結果セットをJSONLファイルにストリーミングできるJavaアプリケーションを構築しようとしていますが、任意の JDBC で実行したいと考えていますDataSource
。Python では、SQL クライアントの結果をジェネレータとして扱い、 を呼び出すのは簡単json.dumps()
です。ただし、このコードでは、書き出す前にすべてをメモリに入れているように見え、通常、ヒープとガベージ コレクションの例外が発生します。これを実行するために必要なクエリは非常に大きく、最大 10 GB の生データが返されます。実行時間は、毎回機能する限り、主要な関心事ではありません。
行ごとにフラッシュを呼び出してみましたが(これはばかげています)、小さなデータセットでは役立ちますが、大きなデータセットでは役に立たないようです。これを簡単にやってのけるために使用できる戦略を誰かが提案できますか?
私の SQL クライアント クラスでは、Apache DbUtils を使用QueryRunner
してs のMapListHandler
リストを作成しています。Map
public List<Map<String, Object>> query(String queryText) {
try {
DbUtils.loadDriver("com.microsoft.sqlserver.jdbc.Driver");
// this function just sets up all the connection properties. Ommitted for clarity
DataSource ds = this.initDataSource();
StatementConfiguration sc = new StatementConfiguration.Builder().fetchSize(10000).build();
QueryRunner queryRunner = new QueryRunner(ds, sc);
MapListHandler handler = new MapListHandler();
return queryRunner.query(queryText, handler);
} catch (Exception e) {
logger.error(e.getMessage());
e.printStackTrace();
return null;
}
}
JsonLOutputWriter
クラス:
JsonLOutputWriter(String filename) {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.serializeNulls();
this.gson = gsonBuilder.create();
try {
this.writer = new PrintWriter(new File(filename), ENCODING);
} catch (FileNotFoundException | UnsupportedEncodingException e) {
e.printStackTrace();
}
}
void writeRow(Map row) {
this.writer.println(this.gson.toJson(row));
}
void flush() {
this.writer.flush();
}
主な方法:
JsonLOutputWriter writer = new JsonLOutputWriter(outputFile)
for (Map row : client.query(inputSql)) {
writer.writeRow(row);
}
writer.flush()