0

このアプリケーションでは、 Windows Serviceを使用してレポートを生成しています。レポートのデータは、ストアド プロシージャを使用してSQL Serverから取得されます。一部のシナリオでは、返される結果セットに 250,000 レコードが含まれます (この部分については支援できません。また、これについて計算を行う必要があるため、このデータが一度に必要になります)。

問題

アプリケーションはリーダーでこのデータを取得し、カスタム オブジェクトのカスタム コレクションでこのデータセットを変換しています。データが巨大であるため、完全なデータをカスタム オブジェクトに格納できず、メモリ不足になります。レコードの実行中にプロセスの使用状況をタスク マネージャーで確認すると、非常に高くなり、CPU 使用率も高くなります。

この場合、何をすべきかわかりません。

  1. CLR で実行されている単一のプロセスに割り当てられるメモリのサイズを増やすことはできますか?
  2. 他の回避策はありますか?

どんな助けでも本当に感謝します

  1. 一度にすべてのデータが必要な理由 : 完全な結果セットに対して計算を行う必要がある
  2. ADO.NET を使用して、データ セットをカスタム オブジェクト (コレクション) に変換しています。
  3. 私たちのシステムは32ビットです
  4. データをページングできません
  5. 計算を SQL サーバーに移動できません

このスタック トレースが役立つ場合があります。

タイプ 'System.OutOfMemoryException' の例外がスローされました。サーバー スタック トレース: System.Collections.Generic.Dictionary 2.ValueCollection.System.Collections.Generic.IEnumerable<TValue>.GetEnumerator() at System.Linq.Enumerable.WhereEnumerableIterator1.MoveNext() で System.Collections.Generic.List 1.InsertRange(Int32 index, IEnumerable1 コレクション) で System.Collections.Generic.List 1.AddRange(IEnumerable1 コレクション) で MyProject.Common.Data.DataProperty.GetPropertiesForType( MyProject.Common.Data.Extensions.GetProperties[T](T target の C:\Ashish-Stuff\Projects\HCPA\Dev Branch\Common\Benefits.Common\Data\DataProperty.shared.cs:line 60 に t) と入力します。 ) in C:\Ashish-Stuff\Projects\HCPA\Dev Branch\Common\Benefits.Common\Data\Extensions.shared.cs:line 30 at MyProject.Common.Data.Factories.SqlServerDataFactoryContract 1.GetData(String procedureName, IDictionary2 つのパラメーター、Nullable 1 languageId, Nullable1 pageNumber、Nullable `1ページサイズ)

ありがとう、アシッシュ

4

3 に答える 3

0

このエラーが発生している場所を強調したコードサンプルをご覧ください。それはデータプル自体にありますか(リーダーにデータを入力します)、それともオブジェクトを作成してカスタムコレクションに追加します(コレクションにデータを入力します)。

私は以前にも同様の問題を抱えており、非常に大きなデータセットを扱っていましたが、可能な限り長い間ストリームに残すことで大きな成功を収めました。ストリームはデータをメモリに直接保持し、オブジェクトの構築が完了するまで、混乱全体に直接アクセスできるものはありません。スタックトレースに「MoveNext」操作のエラーが表示されている場合、これは機能しない可能性があります。次に、データをチャンク化して、一度に10k行か何かを取得してみてください。これは、SQLで実行できることを知っています。ただし、データの読み取りにかなり時間がかかります。

編集

これをデータベースからローカルストリームに読み込んでからパスする場合(閉じないように注意してください)、これらの問題に遭遇することはありません。オープンストリームとオープンリーダーで渡すことができるデータラッパークラスを作成します。データをストリームに保存してから、ラッパー関数を使用して、そこから必要な特定のデータを読み取ります。GetSumOfXField()またはなどなど...データがライブオブジェクトに含まれることAverageOfYValues()はありませんが、データベースに戻ってデータを取得する必要はありません。

疑似例

    public void ReadingTheDataFunction()
    {
        DBDataReader reader = dbCommand.ExecuteReader();
        MyDataStore.FillDataSource(reader)
    }

    private void FillDataSource(DbDataReader reader)
    {
        StreamWriter writer = new StreamWriter(GlobaldataStream);
        while (reader.Read())
            writer.WriteLine(BuildStringFromDataRow(reader));
        reader.close();
    }

    private CustomObject GetNextRow()
    {
        String line = GlobalDataReader.ReadLine();
        //Parse String to Custom Object
        return ret;
    }

そこからMyDataStoreを回って、ストリームとリーダーが閉じられていない限り、位置を移動したり、個々のエントリを探したり、合計や平均をコンパイルしたりすることができます。インターフェイス関数を介してのみ対話する限り、ライブオブジェクトを処理しません。

于 2012-07-23T19:37:22.967 に答える
0

私の最初のことは、ストアドプロシージャによってSql-Server側で計算を行うことができるということでした。このアプローチにはSql-Serverジェダイが必要だと思います...しかし、とにかく、そのようなアプローチを検討しましたか?

于 2012-07-23T16:00:42.493 に答える
0

データの 1,000 行ごとに、オブジェクトのカスタム コレクションをディスクのどこかにシリアル化できますか? 次に、データを返すときに、それらのファイルからページ付けしますか?

250 万行のデータをプルバックする必要がある理由に関するユース ケースの詳細情報が役立ちます。

于 2012-07-23T15:07:25.387 に答える