11

DB から大量のデータを取得する必要があるアプリケーションがあります。これらの行をすべて取得できなかったため (2,000,000 行に近い...)、分割して分割し、毎回 SQL クエリを実行して、毎回 200,000 行しか取得しませんでした。

すべてのデータを入力する DataTable を使用します (つまり、2,000,000 行すべてが存在する必要があります)。

最初の数回は問題ありません。その後、OutOfMemoryException で失敗します。

私のコードは次のように機能します:

private static void RunQueryAndAddToDT(string sql, string lastRowID, SqlConnection conn, DataTable dt, int prevRowCount)
    {
        if (string.IsNullOrEmpty(sql))
        {
            sql = generateSqlQuery(lastRowID);
        }

        if (conn.State == ConnectionState.Closed)
        {
            conn.Open();
        }

        using (IDbCommand cmd2 = conn.CreateCommand())
        {
            cmd2.CommandType = CommandType.Text;
            cmd2.CommandText = sql;
            cmd2.CommandTimeout = 0;

            using (IDataReader reader = cmd2.ExecuteReader())
            {
                while (reader.Read())
                {
                    DataRow row = dt.NewRow();
                    row["RowID"] = reader["RowID"].ToString();
                    row["MyCol"] = reader["MyCol"].ToString();
                    ... //In one of these rows it returns the exception.

                    dt.Rows.Add(row);
                }
            }
        }

        if (conn != null)
        {
            conn.Close();
        }

        if (dt.Rows.Count > prevRowCount)
        {
            lastRowID = dt.Rows[dt.Rows.Count - 1]["RowID"].ToString();
            sql = string.Empty;
            RunQueryAndAddToDT(sql, lastRowID, conn, dt, dt.Rows.Count);
        }
    }

リーダーが行を収集し続けているように思えます。そのため、3 回目または 2 回目のラウンドでのみ例外がスローされます。

使用してメモリをきれいにするべきではありませんか?私の問題を解決できるものは何ですか?

注: 説明する必要があります。これらの行をすべてデータテーブルに取得する以外に選択肢はありません。後で操作を行うため、行の順序が重要であり、分割できないことがあります。いくつかの行のデータを取得して1行に設定するなど、あきらめることはできません。

ありがとう。

4

4 に答える 4

17

Visual Studio の既定のコンパイル モードである 32 ビット プロセスではなく、64 ビット プロセスをビルドしていることを確認します。これを行うには、プロジェクトを右クリックし、[プロパティ] -> [ビルド] -> [プラットフォーム ターゲット: x64] を選択します。他の 32 ビット プロセスと同様に、32 ビットでコンパイルされた Visual Studio アプリケーションには 2 GB の仮想メモリ制限があります。

64 ビット プロセスにはこの制限がありません。64 ビット ポインターを使用するため、理論上の最大アドレス空間は 16 エクサバイト (2^64) です。実際には、Windows x64 ではプロセスの仮想メモリが 8TB に制限されています。メモリ制限の問題の解決策は、64 ビットでコンパイルすることです。

ただし、Visual Studio でのオブジェクトのサイズは既定で 2 GB に制限されています。合計サイズが 2GB を超える複数のアレイを作成できますが、デフォルトでは 2GB を超えるアレイを作成することはできません。それでも 2GB を超える配列を作成したい場合は、次のコードを app.config ファイルに追加してください。

<configuration>
  <runtime>
    <gcAllowVeryLargeObjects enabled="true" />
  </runtime>
</configuration>
于 2013-06-26T14:06:13.310 に答える
3

追加し続けるすべての行から DataTable が非常に大きくなるため、単にメモリが不足していると思います。

この場合、別のパターンを試してみてください。

行をリスト (または DataTable) にバッファリングする代わりに、行が到着したときに使用できるように単純に行を生成できますか?

于 2012-12-24T11:23:42.370 に答える
3

あなたは を使用しているので、私が使用しDataTableていたランダムな問題を共有させてください。ビルド プロパティを確認します。DataTable がメモリ不足の例外をランダムにスローするという問題がありました。結局のところ、プロジェクトの Build Platform ターゲットは に設定されていましたPrefer 32-bit。そのオプションの選択を解除すると、ランダムなメモリ不足の例外がなくなりました。

于 2016-03-23T20:32:24.000 に答える