4

私はこのようなコードを持っています:

public bool Set(IEnumerable<WhiteForest.Common.Entities.Projections.RequestProjection> requests)
    {
        var documentSession = _documentStore.OpenSession();
        //{
        try
        {
            foreach (var request in requests)
            {
                documentSession.Store(request);
            }
            //requests.AsParallel().ForAll(x => documentSession.Store(x));
            documentSession.SaveChanges();
            documentSession.Dispose();
            return true;
        }
        catch (Exception e)
        {
            _log.LogDebug("Exception in RavenRequstRepository - Set. Exception is [{0}]", e.ToString());
            return false;
        }
        //}
    }

このコードは何度も呼び出されます。通過した約50,000のドキュメントに到達した後、OutOfMemoryExceptionが発生します。理由は何ですか?おそらくしばらくして、新しいDocumentStoreを宣言する必要がありますか?

ありがとうございました

**

  • アップデート:

**

最終的に、Batch /PatchAPIを使用して必要な更新を実行しました。ここでディスカッションを見ることができます:https://groups.google.com/d/topic/ravendb/3wRT9c8Y-YE/discussion

基本的に、オブジェクトの1つのプロパティを更新するだけでよく、すべてのオブジェクトをJSONに再シリアル化することについてのayendesのコメントを検討した後、次のようにしました。

internal void Patch()
    {
        List<string> docIds = new List<string>() { "596548a7-61ef-4465-95bc-b651079f4888", "cbbca8d5-be45-4e0d-91cf-f4129e13e65e" };
        using (var session = _documentStore.OpenSession())
        {
            session.Advanced.DatabaseCommands.Batch(GenerateCommands(docIds));
        }
    }

    private List<ICommandData> GenerateCommands(List<string> docIds )
    {
        List<ICommandData> retList = new List<ICommandData>();

        foreach (var item in docIds)
        {
            retList.Add(new PatchCommandData()
            {
                Key = item,
                Patches = new[] { new  Raven.Abstractions.Data.PatchRequest () {
                Name = "Processed",
                Type = Raven.Abstractions.Data.PatchCommandType.Set,
                Value = new RavenJValue(true)
            }}});
        }

        return retList;
    }

お役に立てれば ...

どうもありがとう。

4

3 に答える 3

4

現在のプロジェクトでこれを行いました。データをチャンクに分割し、各チャンクを新しいセッションに保存しました。これはあなたにも役立つかもしれません。

この例では、一度に 1024 個のドキュメントをチャンクすることを示していますが、チャンクする価値があると判断するには少なくとも 2000 個必要です。これまでのところ、挿入は 4096 のチャンク サイズで最高のパフォーマンスを得ました。これは、ドキュメントが比較的小さいためだと思います。

internal static void WriteObjectList<T>(List<T> objectList)
{
    int numberOfObjectsThatWarrantChunking = 2000;  // Don't bother chunking unless we have at least this many objects.

    if (objectList.Count < numberOfObjectsThatWarrantChunking)
    {
        // Just write them all at once.
        using (IDocumentSession ravenSession = GetRavenSession())
        {
            objectList.ForEach(x => ravenSession.Store(x));
            ravenSession.SaveChanges();
        }

        return;
    }

    int numberOfDocumentsPerSession = 1024;  // Chunk size

    List<List<T>> objectListInChunks = new List<List<T>>();

    for (int i = 0; i < objectList.Count; i += numberOfDocumentsPerSession)
    {
        objectListInChunks.Add(objectList.Skip(i).Take(numberOfDocumentsPerSession).ToList());
    }

    Parallel.ForEach(objectListInChunks, listOfObjects =>
    {
        using (IDocumentSession ravenSession = GetRavenSession())
        {
            listOfObjects.ForEach(x => ravenSession.Store(x));
            ravenSession.SaveChanges();
        }
    });
}

private static IDocumentSession GetRavenSession()
{
    return _ravenDatabase.OpenSession();
}
于 2012-04-05T16:27:07.623 に答える
2

1 回の呼び出しですべてを保存しようとしていますか? DocumentSession は、渡すすべてのオブジェクトをサーバーへの単一の要求に変換する必要があります。つまり、サーバーへの書き込みに大量のメモリが割り当てられる可能性があります。通常、一括保存を行う場合、約 1,024 個のアイテムのバッチをお勧めします。

于 2012-04-05T16:17:04.610 に答える
0

DocumentStoreは使い捨てクラスなので、各チャンクの後にインスタンスを破棄することでこの問題を回避しました。これが操作を実行する最も効率的な方法であるとは思えませんが、重大メモリ オーバーヘッドの発生を防ぐことができます。

そのような「すべて削除」操作を実行していました。ブロックが各チャンクの後にと オブジェクトのusing両方を破棄していることがわかります。DocumentStoreIDocumentSession

static DocumentStore GetDataStore()
{
    DocumentStore ds = new DocumentStore
    {
        DefaultDatabase = "test",
        Url = "http://localhost:8080"
    };

    ds.Initialize();
    return ds;
}

static IDocumentSession GetDbInstance(DocumentStore ds)
{
    return ds.OpenSession();
}

static void Main(string[] args)
{
    do
    {
        using (var ds = GetDataStore())
        using (var db = GetDbInstance(ds))
        {
            //The `Take` operation will cap out at 1,024 by default, per Raven documentation
            var list = db.Query<MyClass>().Skip(deleteSum).Take(5000).ToList(); 
            deleteCount = list.Count;
            deleteSum += deleteCount;

            foreach (var item in list)
            {
                db.Delete(item);
            }
            db.SaveChanges();
            list.Clear();
        }
    } while (deleteCount > 0);
}
于 2013-10-30T15:05:31.223 に答える