0

テーブルをループし、すべての行のいくつかの値を変更し、変更をデータベースに保存する次の方法があります。処理を高速化するために、10,000 行のセットでデータを取得しています。これは、2,500 万を超えるレコードを含む大きなテーブルです。

問題は、アプリケーションがメモリを解放していないように見えることです。records変数をガベージ コレクターに再宣言するnothingか、ガベージ コレクターを明示的に呼び出しようとしましたが、メモリはそこにとどまります。組み込みの VS10 プロファイラーを実行するsystem.linq.enumerable.tolist()と、メモリの 98% 以上を占めるメソッドが原因であることがわかります。への呼び出し後にそのメモリを解放するにはどうすればよいsaveChangesですか?

db = New databaseEntities
Dim size = 25000000
Dim stepSize = 10000
For i = 0 to size Step stepSize
  Dim sql = (From A In db.table).OrderBy(Function(A) A.Column).Skip(i).Take(stepSize)
  Dim records As New List(Of table)
  records = sql.ToList
  For Each record In records
    'do some work
  Next
  db.SaveChanges()
  records = Nothing
  GC.Collect()
Next
4

4 に答える 4

0

エンティティを更新する必要がない場合は、 MergeOption.NoTracking. コンテキストはエンティティへの参照を保持しなくなり、修正も行いません。

于 2010-11-04T14:40:42.373 に答える
0

リポジトリは、追跡している各エンティティへの参照を保持しているため、リポジトリがライブで追跡している間はエンティティを破棄できません。つまり、処理が完了したら、リポジトリを破棄するか、各エンティティをデタッチする必要があります。

オプション 1) 「何らかの作業を行う」ことがレコードを返す順序に影響しない場合は、databaseEntities の作成を For ループ内に移動し、using ブロックで宣言することができます。これにより、エンティティの各ブロックが for ループのたびに解放されるはずです

オプション 2) 操作が本質的に並列であり、1 つの「テーブル」エンティティに対して行っていることが他のエンティティに依存していない場合は、db.SaveChanges の後に databaseEntities.Detach(record) を呼び出すことができます。これにより、ガベージが有効になります。エンティティのスペースを再利用するコレクター。

あなたのコードを見ると、これらのいずれかが使用できると思われます

于 2010-11-04T11:48:38.017 に答える
0

多分あなたはこれを試すことができます:(私はそれをテストしませんでした)

db.SaveChanges()
For Each record In records
    record.dispose ''only if class table got a dispose method
Next
records.clear
records = Nothing
于 2010-11-04T11:23:41.967 に答える
0

私は決して Linq to SQL の専門家ではありませんが、DataContext は読み取ったすべての行をキャッシュするので、キャッシュを空にするか、DataContext への参照を失う必要があると思います。

于 2010-11-04T11:29:42.387 に答える