C# 插入RavenDB;最快的方式

C# 插入RavenDB;最快的方式,c#,asynchronous,insert,nosql,ravendb,C#,Asynchronous,Insert,Nosql,Ravendb,我想从一个文本文件(每行是一个类似csv的条目)中导入1亿个条目到RavenDB数据库中。最快的方法是什么 补充说明: 我还没有任何索引(我将在插入数据后创建它们)。RavenDB在本地机器上以服务模式运行,没有任何安全增强(因为我仍在测试RavenDB)。此测试将在2台不同的机器上运行,1)2核4GB ram 2)8核12 GB ram 我已经将部分数据(200万条)插入到RavenDB中,但速度并没有我希望的那么快。通过使用OpenAsyncSession,每1024条记录调用一次SaveC

我想从一个文本文件(每行是一个类似csv的条目)中导入1亿个条目到RavenDB数据库中。最快的方法是什么

补充说明:

我还没有任何索引(我将在插入数据后创建它们)。RavenDB在本地机器上以服务模式运行,没有任何安全增强(因为我仍在测试RavenDB)。此测试将在2台不同的机器上运行,1)2核4GB ram 2)8核12 GB ram

我已经将部分数据(200万条)插入到RavenDB中,但速度并没有我希望的那么快。通过使用OpenAsyncSession,每1024条记录调用一次SaveChangesSync,再调用OpenAsyncSession创建一个新的会话,在大约500000个条目之后不等待返回任务(由SaveChangesSync返回),我得到了一个“索引超出范围”的异常,我无法根除它。但若我等待任务结束(通过创建和内核数量相同的任务),这个过程将成功,但速度不够快

此代码已成功运行:

using (var reader = new StreamReader(@"D:\*\DATA.TXT", Encoding.UTF8))
{
    string line = null;
    IAsyncDocumentSession session = null;

    var tasks = new List<Task>();
    var locCount = 0;

    while ((line = reader.ReadLine()) != null)
    {
        if (string.IsNullOrWhiteSpace(line)) continue;

        var loc = Parse(line);

        if (session == null) session = documentStore.OpenAsyncSession();

        session.Store(loc);
        locCount++;

        if (locCount % 1024 == 0 && session != null)
        {
            try
            {
                var t = session.SaveChangesAsync();
                tasks.Add(t);
                session = null;
            }
            catch (Exception x)
            {
                // ... something ...
            }
        }

        if (tasks.Count >= NUMBER_OF_CORES)
        {
            Task.WaitAll(tasks.ToArray());
            tasks.Clear();
        }
    }

    if (session != null)
    {
        if (tasks.Count > 0)
        {
            Task.WaitAll(tasks.ToArray());
            tasks.Clear();
        }
        session.SaveChangesAsync().Wait();
        session = null;
    }
}
使用(var reader=newstreamreader(@“D:\*\DATA.TXT”,Encoding.UTF8))
{
字符串行=null;
IAsyncDocumentSession=null;
var tasks=新列表();
var-locCount=0;
而((line=reader.ReadLine())!=null)
{
如果(string.IsNullOrWhiteSpace(line))继续;
var loc=解析(行);
如果(session==null)session=documentStore.OpenAsyncSession();
会话存储(loc);
locCount++;
if(locCount%1024==0&&session!=null)
{
尝试
{
var t=session.SaveChangesAsync();
任务。添加(t);
会话=空;
}
捕获(异常x)
{
//…有些事。。。
}
}
if(tasks.Count>=内核的数量)
{
Task.WaitAll(tasks.ToArray());
任务。清除();
}
}
if(会话!=null)
{
如果(tasks.Count>0)
{
Task.WaitAll(tasks.ToArray());
任务。清除();
}
session.saveChangesSync().Wait();
会话=空;
}
}
谢谢你,卡维

这里有很多问题

1) RavenDB模型很少映射到CSV文件。如果你有一个CSV文件,你通常有表格格式,而这不是一个很好的格式移植到RavenDB。通过得到好的模型,你可能会得到更好的结果

2) 如果(tasks.Count>=numberofcores)不使用
编码,则将生成尽可能多的任务(受从文件中读取行的限制,这非常快)。
这将倾向于生成数千个并发任务,并且会使RavenDB一次可以插入的请求数量过载

3) 使用标准会话,使用1024-2048的批大小。就让它跑吧。 RavenDB在优化方面非常出色,我希望您可以轻松地看到每秒数千次插入


但是,同样,您可能建模错误。

如果您不等待完成,它当然会看起来很快。因为处理尚未完成。这不是有效的基准。文档数据库与“记录”无关。您可能希望了解如何对这些数据进行建模以适应文档数据库。对于类似场景的示例,请参见和@synhershko,我知道在某种程度上,这是关于文档的,我在这里使用了“记录”一词,因为当时我没有更好的词来形容它;也许是“进入”?“反对”?“信息”?我不知道…谢谢!我的观点是,你可能需要做的插入比你想象的要少很多。最快的方法是使用一个简单的控制台应用程序成批完成这项工作——如果您对每一批应用程序调用SaveChanges,会话API将为您完成这项工作。您会发现,从源代码中读取数据将花费大部分时间。@usr处理已完成,RavenDB是ACID。索引可能还没有跟上,但所有信息都已可用。