質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.89%

C# データベースでデータ抽出時にメモリ不足を起こす。

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 4,172

TAKAYASU

score 140

いつもお世話になってます。
10月からC#とSQLServerで検索や登録等のやり取りをする機会が出てきまして現在勉強しています。

//select関数に下記情報を渡す。
        //第一引数 string sql文
        //第二引数 HashTable パラメータ
        //第三引数 SqlConnection コネクション
        public DataTable select(string sql, Hashtable prms = null, SqlConnection pconn = null)
        {
            SqlConnection objConn = pconn;
            DataTable dataTable = null;
            try
            {
                if (pconn == null)
                {
                    /*** データベースに接続 ***/
                    objConn = new SqlConnection(connection_str);
                    objConn.Open();
                }

                //アダプタ作成
                SqlDataAdapter daAuthors 
                = new SqlDataAdapter();

                daAuthors.SelectCommand = new SqlCommand(sql, objConn);

                if (prms != null)
                {
                    foreach (string key in prms.Keys)
                    {
                        //パラメータ格納
                        daAuthors.SelectCommand.Parameters.Add(new SqlParameter(key, prms[key]));
                    }
                }

                //データセット作成
                DataSet dataSet = new DataSet();
                daAuthors.FillSchema(dataSet, SchemaType.Source, "DATA");

                //ここでエラーを吐く
                daAuthors.Fill(dataSet, "DATA");

                //取得したデータを代入する。
                dataTable = dataSet.Tables["DATA"];
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                if (pconn == null && objConn != null)
                {
                    objConn.Close();
                }
            }
            return dataTable;
        }

問題点

上記コードで取得件数が1000件以上ある場合、2分以上経過したあたりからOutOfMemoryを吐き出してしまいます。

知りたいこと

取得するデータ量が多く、メモリ不足を起こしてしまう場合
どのような対策を講じればよいのでしょうか?
コードよりも手法を知りたいです。

データベースはまだまだ勉強中の身ですので初歩的な質問かもしれませんがよろしくお願い致します!
不備等ありましたらご指摘の程お願い致します!

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

一度に大量のデータをメモリに入れるとメモリリークしやすいので,クエリを複数に分けて一回あたりに持ってくるレコード数の単位を区切りながら実行したり,LazyLoadingという仕組みを使って逐次読み込みでレコードを取得しメモリを解放するようにする仕組みを作ることが多いです。全てのレコードをメモリに突っ込まなければできない処理は基本的にマシンスペックを上げるしかありません。

検索した所こちらの記事が引っかかりましたが,lazyload C#などで調べると色々出てくるので調べて見てください。

上の例はreturnで実装されていますが普通はyieldを使う実装が多いとおもいます。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/10/31 10:20 編集

    とてもわかりやすい回答ありがとうございます!

    >一度に大量のデータをメモリに入れるとメモリリークするので,クエリを複数に分けて一回あたりに持ってくるレコード数の単位を区切りながら実行したり,LazyLoadingという仕組みを使って逐次読み込みでレコードを取得しメモリを解放するようにする仕組みを作ることが多いです。

    どうしようどうしようと考えていた時は
    「別のクラスを使う」という方法しか思い浮かばず、そういうやり方があることを知りませんでした。
    LazyLoadingも調べてみました、ためになる情報ありがとうございます!

    >上の例はreturnで実装されていますが普通はyieldを使う実装が多いとおもいます。
    yieldですか・・・これまで使ったことがないのでまずはどういったものかを調べてみる必要がありそうです。。。
    理解できたらyieldも使おうと考えてます!

    ありがとうございました!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.89%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる