1

ユーザーがリンクをクリックしてデータのリストをダウンロードできる Web アプリケーションがあります。それが行うことは、MS sql サーバー データベースでストアド プロシージャを起動することです。つまり、14 列とすべての文字列で行をフェッチします。それを取得して結果セットから抽出したら、それをクライアントのマシン上の csv ファイルに直接ストリーミングします。そうすれば、ストリーミング操作を開始する前に、メモリ内に中間ドメイン オブジェクト (返される行数に等しい) を作成して節約できます。また、結果セット全体がメモリにロードされるまで待機しません。ただし、たとえば、そのようなデータのインスタンスが 80000 あるクライアントの場合、メモリはまだ 50 mb 急増しています。その後、約 20 mb の減少があり、しばらくの間そのレベルにとどまります。jconsole で Perform GC を実行すると、残りの 30 MB も解放されます。何が原因でそれがしばらく続くのかわかりません。また、50 mb のスパイクは、1.2 ギガのメモリで実行されているアプリケーションでは受け入れられません。より大きなクライアントの場合、400 mb まで跳ね上がり、アプリケーションがフリーズするか、OOM が発生します。これを達成する方法について何か提案はありますか? 注意してください - 私は同じことを別の場所に実装しました.5秒で同じサイズで異なるデータ(6列)のファイルがダウンロードされ、メモリスパイクはわずか5 MBです。この場合、Sql Mnagament スタジオで実行した場合でも、ストアド プロシージャを実行するのにわずか 4 秒しかかかりませんでした。しかし、私が大きなスパイクを得ているものは、クエリ自体の実行に45秒かかり、多くの検証を通過するデータに基づいています. それは悪影響を及ぼしますか?プリペアドストメントの setFetchSize() で 1000 のチャンクをフェッチしているので、そうならないことを望んでいました より大きなクライアントの場合、400 mb まで跳ね上がり、アプリケーションがフリーズするか、OOM が発生します。これを達成する方法について何か提案はありますか? 注意してください - 私は同じことを別の場所に実装しました.5秒で同じサイズで異なるデータ(6列)のファイルがダウンロードされ、メモリスパイクはわずか5 MBです。この場合、Sql Mnagament スタジオで実行した場合でも、ストアド プロシージャを実行するのにわずか 4 秒しかかかりませんでした。しかし、私が大きなスパイクを得ているものは、クエリ自体の実行に45秒かかり、多くの検証を通過するデータに基づいています. それは悪影響を及ぼしますか?プリペアドストメントの setFetchSize() で 1000 のチャンクをフェッチしているので、そうならないことを望んでいました より大きなクライアントの場合、400 mb まで跳ね上がり、アプリケーションがフリーズするか、OOM が発生します。これを達成する方法について何か提案はありますか? 注意してください - 私は同じことを別の場所に実装しました.5秒で同じサイズで異なるデータ(6列)のファイルがダウンロードされ、メモリスパイクはわずか5 MBです。この場合、Sql Mnagament スタジオで実行した場合でも、ストアド プロシージャを実行するのにわずか 4 秒しかかかりませんでした。しかし、私が大きなスパイクを得ているものは、クエリ自体の実行に45秒かかり、多くの検証を通過するデータに基づいています。それは悪影響を及ぼしますか?プリペアドストメントの setFetchSize() で 1000 のチャンクをフェッチしているので、そうならないことを望んでいました これを達成する方法について何か提案はありますか? 注意してください - 私は同じことを別の場所に実装しました.5秒で同じサイズで異なるデータ(6列)のファイルがダウンロードされ、メモリスパイクはわずか5 MBです。この場合、Sql Mnagament スタジオで実行した場合でも、ストアド プロシージャを実行するのにわずか 4 秒しかかかりませんでした。しかし、私が大きなスパイクを得ているものは、クエリ自体の実行に45秒かかり、多くの検証を通過するデータに基づいています. それは悪影響を及ぼしますか?プリペアドストメントの setFetchSize() で 1000 のチャンクをフェッチしているので、そうならないことを望んでいました これを達成する方法について何か提案はありますか? 注意してください - 私は同じことを別の場所に実装しました.5秒で同じサイズで異なるデータ(6列)のファイルがダウンロードされ、メモリスパイクはわずか5 MBです。この場合、Sql Mnagament スタジオで実行した場合でも、ストアド プロシージャを実行するのにわずか 4 秒しかかかりませんでした。しかし、私が大きなスパイクを得ているものは、クエリ自体の実行に45秒かかり、多くの検証を通過するデータに基づいています. それは悪影響を及ぼしますか?プリペアドストメントの setFetchSize() で 1000 のチャンクをフェッチしているので、そうならないことを望んでいました しかし、私が大きなスパイクを得ているものは、クエリ自体の実行に45秒かかり、多くの検証を通過するデータに基づいています. それは悪影響を及ぼしますか?プリペアドストメントの setFetchSize() で 1000 のチャンクをフェッチしているので、そうならないことを望んでいました しかし、私が大きなスパイクを得ているものは、クエリ自体の実行に45秒かかり、多くの検証を通過するデータに基づいています. それは悪影響を及ぼしますか?プリペアドストメントの setFetchSize() で 1000 のチャンクをフェッチしているので、そうならないことを望んでいました

ここにコードのスニペットがあります

Connection connection = null;
        PreparedStatement statement = null;
        ResultSet rs = null;
        OutputStream outputStream = null;
        BufferedWriter bufferedWriter = null;
        try
        {
            response.setContentType("application/save");
            response.setHeader("Content-Disposition", "attachment; filename="
                    + link.getFileName());

            outputStream = response.getOutputStream();

            bufferedWriter = new BufferedWriter(new OutputStreamWriter(
                    outputStream));

            connection = dataSource.getConnection();
            statement = connection.prepareStatement(link.getQuery());

            statement.setFetchSize(1000);
            statement.setInt(1, form.getSelectedClientId());

            rs = statement.executeQuery();

            while (rs.next())
            {

                bufferedWriter
                        .write(getCsvRowString(new String[]
                        { rs.getString(1), rs.getString(2), rs.getString(3),
                                rs.getString(4), rs.getString(5),
                                rs.getString(6), rs.getString(7),
                                rs.getString(8), rs.getString(9),
                                rs.getString(10), rs.getString(11),
                                rs.getString(12), rs.getString(13),
                                rs.getString(14), rs.getString(15),
                                rs.getString(16), rs.getString(17),
                                rs.getString(18) }));

            }

        } catch (final Exception e)
        {
            log.error("Error in downloading extracts " + e.getMessage());
            throw e;
        } finally
        {
            if (bufferedWriter != null)
            {
                bufferedWriter.flush();
                bufferedWriter.close();
            }
            if (outputStream != null)
            {
                outputStream.close();
            }

            rs.close();
            statement.close();
            connection.close();
        }
4

1 に答える 1

1

おそらく、古代の MS SQL JDBC ドライバーはsetFetchSize()ヒントを無視しています (この回答https://stackoverflow.com/a/1982109/116509を参照してください)。Horizo​​n のような jTDS ドライバーを使用してみてください。

于 2012-04-27T11:14:17.643 に答える