我有这样的代码:
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 / Patch API来执行我需要的更新。 您可以在此处查看讨论: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;
}
希望这会有所帮助......
非常感谢。
答案 0 :(得分: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();
}
答案 1 :(得分:2)
您是否尝试在一次通话中保存所有内容? DocumentSession需要将您传递给它的所有对象转换为对服务器的单个请求。这意味着它可能会为写入服务器分配大量内存。 通常我们建议您批量生产大约1,024件商品。
答案 2 :(得分:0)
DocumentStore
是一个一次性类,所以我通过在每个块之后处理实例来解决这个问题。我高度怀疑这是运行操作的最有效方式,但它可以防止发生重大内存开销。
我正在运行一种“全部删除”操作。您可以看到using
块在每个块之后同时处理DocumentStore
和IDocumentSession
个对象。
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);
}