【问题标题】:how to append a sql query to existing file in java?如何将sql查询附加到java中的现有文件?
【发布时间】:2019-06-14 10:07:21
【问题描述】:

我目前正在编写一个 java 代码,它允许我查询数据库并将其内容提取到文件中。

到目前为止,小请求没有问题。

但我很快将不得不提取大量数据,并且我已经尝试了几天来实施最有效的解决方案,以尽可能限制内存消耗。

因为我一发出重要请求,源机和目标机的内存就饱和了。

我在redhat linux环境下使用的java版本是java-1.8.0

到目前为止,我已经能够将我的查询结果重定向到一个文件。但是在查阅了大量文档后,我可以看到有很多不同的方法可以限制内存消耗。

DriverManager.registerDriver(new              
com.wily.introscope.jdbc.IntroscopeDriver());
Connection conn = DriverManager.getConnection("jdbc:introscope:net//" +     
user + ":" + password + "@" + hostname + ":" + port);       

String query = "select * from metric_data"
                + " where agent='"
                + agents_filter
                + "' and metric='"
                + metrics_filter
                + "' and timestamp between "
                + queryInterval;

Statement ps=conn.createStatement();
ResultSet rs=ps.executeQuery(query);

rs.setFetchSize(Size);
ResultSetMetaData rsm = rs.getMetaData();
File output = new File("result");
PrintWriter out = new PrintWriter(new BufferedWriter(
    new OutputStreamWriter(
    new FileOutputStream(output), "UTF-8")), false);

    for(int i = 1; i <= rs.getMetaData().getColumnCount(); i++){
    String colName = rs.getMetaData().getColumnName(i);
    out.print(" " + colName + "\t\t" + "|");
        }

        while (rs.next()) {
            for(int i = 1; i <= rs.getMetaData().getColumnCount(); i++){
                String colValue = rs.getString(i);
                out.print(" " + colValue + "\t" + "|");
                                                                        }

                out.println();
                        }


    out.close();
    out.flush();
    rs.close();
    ps.close();
    conn.close();

当前请求已完全加载到内存中,然后重定向到我的文件。但是一旦请求太重要,我就会收到以下消息:

线程“PO:client_main Mailman 2”中的异常 java.lang.OutOfMemoryError: Java 堆空间 线程“UnknownHub Hub Receive 1”中的异常 java.lang.lang.OutOfMemoryError: Java heap space

我希望能够在文件中写入例如 1000 行乘以 1000 行,以免内存饱和。

知道文件有时会达到 40gb

执行时间不是问题,但内存消耗是一个非常重要的标准。

我远不是一个java专业人士,所以我需要你的帮助。

提前感谢您的宝贵时间

【问题讨论】:

    标签: java bufferedwriter


    【解决方案1】:
    1. 通过连接字符串来构造 SQL 字符串是一个安全漏洞。想象一下这些变量是这样的:"1'; DROP ALL TABLES; --"。即使在这里您知道字符串是“安全的”,代码也会更改,并且您不应该养成不良习惯。解决这个问题;你可以使用 PreparedStatement 来修复它。

    2. 元数据不是免费的。缓存那些东西。具体来说,缓存值rs.getMetaData().getColumnCount()

    3. 1234563真的没有比这更快的了。
    4. 关闭后不能刷新,关闭意味着刷新。您可以删除 flush() 行。

    5. 假设您的 fetch 大小不是大得离谱,这段代码中没有任何内容表明会发生内存不足错误。因此,要么是重复调用 getMetaData(这意味着缓存列大小可以解决您的问题),要么是数据库引擎和/或其 JDBC 驱动程序编写不当。我还没有听说过内窥镜,这就是我提到它的原因。如果是这种情况,充其量您可以使用 SQL OFFSETLIMIT 将您的查询分成“页面”,因此不会一次获取太多结果,但在您的 SQL 中没有 ORDER,技术上是数据库引擎可以改变你的顺序,有了它,这个过程可能会变得很慢。

    【讨论】:

    • 首先非常感谢您的回答。但是,基础上没有开发人员资料,Java 对我来说是全新的。你能给我一个例子来格式化吗?预先感谢您的帮助。祝你有美好的一天。
    猜你喜欢
    • 2016-10-23
    • 2010-12-10
    • 1970-01-01
    相关资源
    最近更新 更多