所以我有一个任务要构建,它将把我们数据库中的大量数据存档到JSON中.
为了让您更好地了解正在发生的事情; X有100s的Ys,Y有100s的Zs,依此类推.我正在为每个X,Y和Z创建一个json文件.但是每个X json文件都有一个子数组,其中包含X的子Ys,同样Ys存储了一个子Zs数组.
它比许多情况下更复杂,但你应该从我认为的那个例子中了解所涉及的复杂性.
我正在使用ColdFusion,但它似乎是一个不好的选择,因为它因内存错误而崩溃.在我看来,如果它正在从运行任务时不再引用的内存中删除查询(即:垃圾收集),那么任务应该有足够的内存,但是根据ColdFusion根本没有进行任何垃圾收集,并且必须在请求完成后执行此操作.
因此,我正在寻找有关如何更好地完成我在CF中的任务的建议,或者寻求使用其他语言的建议.
谢谢.
1)如果启用了调试,coldfusion将继续查询,直到页面完成.把它关掉!
2)您可能需要structDelete()查询变量以允许它被垃圾收集,否则它可能会持久存在,只要存在引用它的范围.例如.,
<cfset structDelete(variables,'myQuery') />
3)cfquery将整个ResultSet拉入内存.大多数时候这很好.但是对于大型结果集的报告,您不希望这样.一些JDBC驱动程序支持设置fetchSize,它以前向只读方式允许您一次获得一些结果.这样,您可以处理成千上万行,而不会淹没内存.我只用了不到100mb的堆就在~80秒内生成了一个1GB的csv文件.这需要退出Java.但它一石二鸟.它减少了JDBC驱动程序一次带入的数据量,并且由于您直接使用ResultSet,因此不会遇到提到的cfloop问题@orangepips.当然,它不适合那些没有Java排骨的人.
你可以这样做(你的构建路径中需要cfusion.jar):
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.sql.ResultSet;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import au.com.bytecode.opencsv.CSVWriter;
import coldfusion.server.ServiceFactory;
public class CSVExport {
public static void export(String dsn,String query,String fileName) {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
FileWriter fw = null;
BufferedWriter bw = null;
try {
DataSource ds = ServiceFactory.getDataSourceService().getDatasource(dsn);
conn = ds.getConnection();
// we want a forward-only, read-only result.
// you may want need to use a PreparedStatement instead.
stmt = conn.createStatement(
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY
);
// we only want to go forward!
stmt.setFetchDirect(ResultSet.FETCH_FORWARD);
// how many records to pull back at a time.
// the hard part is balancing memory usage, and round trips to the database.
// basically sacrificing speed for a lower memory hit.
stmt.setFetchSize(256);
rs = stmt.executeQuery(query);
// do something with the ResultSet, for example write to csv using opencsv
// the key is to stream it. you don't want it stored in memory.
// so excel spreadsheets and pdf files are out, but text formats like
// like csv, json, html, and some binary formats like MDB (via jackcess)
// that support streaming are in.
fw = new FileWriter(fileName);
bw = new BufferedWriter(fw);
CSVWriter writer = new CSVWriter(bw);
writer.writeAll(rs,true);
}
catch (Exception e) {
// handle your exception.
// maybe try ServiceFactory.getLoggingService() if you want to do a cflog.
e.printStackTrace();
}
finally() {
try {rs.close()} catch (Exception e) {}
try {stmt.close()} catch (Exception e) {}
try {conn.close()} catch (Exception e) {}
try {bw.close()} catch (Exception e) {}
try {fw.close()} catch (Exception e) {}
}
}
}
Run Code Online (Sandbox Code Playgroud)
弄清楚如何传递参数,记录,将其转换为后台进程(提示:扩展线程)等是不同的问题,但是如果你了解这个代码,那应该不会太困难.
4)也许看杰克逊生成你的json.它支持流式传输,并结合fetchSize和BufferedOutputStream,您应该能够保持内存使用率下降.
| 归档时间: |
|
| 查看次数: |
676 次 |
| 最近记录: |