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

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

ただいまの
回答率

87.96%

CSVTable結合の仕方について

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 1,567

score 13

CSVデータとDBデータを結合する要件があり、
以下のソースを書きましたが、状況次第ではOutOfMemoryが出てしまい、対応に苦慮しています。
なにか良い案があればと思い、質問させていただきました。

            'CSVファイルをDataTableに読み込み
            sDt_CsvBase = mdl_Common.CsvToTable(sCSVFileName)
            'sDt_CSV = dt2Clone(sDt_CsvBase, childKey, System.Type.GetType("System.Int64"))
            sDt_CSV = dt2Clone(sDt_CsvBase, childKey, System.Type.GetType("System.String"))
            sDt_CsvBase.Clear()

            ''DBデータをDataTableに読み込み 
            sDt_DB = DB2Datable(sSQL)
            'CloneするとOutOfMemoryが発生するため実行しない。
            'sDt_DB = dt2Clone(sDt_DBBase, parentKey, System.Type.GetType("System.Int64")) 
            'sDt_DBBase.Clear() 

            'DataSetに統合
            sDs.Tables.Add(sDt_DB)
            sDs.Tables(0).TableName = "DB"
            sDs.Tables.Add(sDt_CSV)
            sDs.Tables(1).TableName = "CSV"


            '親となるテーブルのキー項目定義
            Dim parentColumns(0) As DataColumn
            parentColumns(0) = RelationColumnSet(parentKey, sDs.Tables(0))

            '子となるテーブルのキー項目定義
            Dim childColumns(0) As DataColumn
            childColumns(0) = RelationColumnSet(childKey, sDs.Tables(1))

            'リレーション
            sDs.Relations.Add(New DataRelation("key", parentColumns, childColumns, False))
            dt_Clone = dt_Base.Clone
            dt_Clone.Columns(changeName).DataType = changeType
            For Each dr As DataRow In dt_Base.Rows
                dt_Clone.ImportRow(dr)
            Next

なお、DBはMySQL5.6ですが、権限はSelectしかないため、Createなどは出来ません。
サンプルで実行したものは、DBは30万件、CSVは2万件程度で、
一時的に、Cloneをしているためメモリが倍掛けで増えています。(OutOfMemoryが発生しやすい)

問題としては、CSVは自動で型決定し、DBは元の型は踏襲しているようで
型合わせのためCloneしているのが、今回の問題になっています。

今回のデータは、10桁の数値データを結合条件にしており、
CSVはDobule、DBはVarchar(String型)になっていたため、String型に合わせています。
・Cast(hoge as Unsignd)にしましたが、DoubleとUInt64は型不一致エラー。
・この例ではDobuleにCastすればよいですが、汎用的にするには、あらかじめCSVの型がわからないと難しい。
・0埋め問題もあるので、これも確実ではない。(001と 1の関係)

Datatableに巨大なデータを入れると問題があるという情報はありましたが、
結合の案が思い浮かばなかったため、何か良案があれば教えてください。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • YAmaGNZ

    2019/02/17 18:42

    CSVを読み込む時に、最初から型を合わせて読み込めば複製して型変換を行わないで済みますが、CSV読み込み部を変更できないのですか?
    また、ローカルで別のDBを使用してはダメなのですか?

    キャンセル

  • FujiCandy

    2019/02/18 09:57 編集

    ローカルDBも考えたのですが、DBデータとCSVデータのImportに時間がかかりすぎて、一旦除外していました。ですが、その手も考えておきます。
    なお、CSVは別システムから出力されたデータですが、出力後の加工は可能です。

    キャンセル

回答 2

checkベストアンサー

0

まず、mdl_Common.CsvToTableで作成されるDataTableですが、ここでキーになるデータ型を揃えてしまえば、後にCloneを作る必要がなくなるかと思います。

また、DataTableにてリレーションを張るのではなく、Listなどにデータ格納し、LINQにてJOIN等で結合するなどを考えてもいいのかもしれません。

小手先の方法ですが、32ビットアプリの場合、EDITBINの/largeaddressawareで2Gを超えるメモリを使用できるようにできますので、単純に足りないのであれば、これを行うと改善する可能性もあります。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/02/18 16:44

    色々とありがとうございます。
    データの型ですが、テーブル+項目が多量にあったため、除外してましたが、多量データの場合については、これも視野にいれてみます。
    最悪、DBデータを入れてから、DBの結合キーとなるデータ型に
    CSVのキー項目を変換して対応しようかと思います。(CSVのみClone)

    LINK LINQについては、私が不得手・不勉強でしたので、パフォーマンスとかいいと聞いてますが、外しました。(外部結合などよくわからなかったので)ただ、メモリの使い方等が違うかもしれませんので、視野にいれてみます。

    EDITBINは、初めて知りましたが、こういうのがあるのですね。
    ぜひとも活用してみます。

    キャンセル

0

datatableに巨大なデータをいれると、それだけメモリが圧迫されるのが問題なのでは?
100件なり、1000件なりレコードを区切って、insert文を編集しCSVからDBへ更新するのが望ましいと思います。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/02/18 10:03

    今回の要件としては、
    別システムDB(Mysql)とさらに別システムで出力されたCSVデータ(編集不可)を結合して、新たなCSVデータを作るという話になります。
    Insert文を作るというわけではないのです。
    whereでうまく区切って出力する方法は、検討してみます。

    キャンセル

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

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

関連した質問

同じタグがついた質問を見る