我正在尝试学习如何使用RavenDB,为此我创建了一个基本的例子。 似乎初始化商店和查询需要花费大量时间!
static void Main( string[] args )
{
const bool createNewEntities = true;
var sw = new Stopwatch();
using( var store = new EmbeddableDocumentStore {DataDirectory = "~\\Data"} )
{
sw.Start();
store.Initialize();
sw.Stop();
Console.WriteLine( "Initialized in {0} ms.", sw.ElapsedMilliseconds );
if (createNewEntities)
{
sw.Reset();
sw.Start();
using( var session = store.OpenSession() )
{
sw.Stop();
Console.WriteLine();
Console.WriteLine( "Opened session in {0} ms.", sw.ElapsedMilliseconds );
for( var i = 0; i < 10; i++ )
{
var entity = new EntityA( "Entity A " + DateTime.Now.ToLongTimeString() );
sw.Reset();
sw.Start();
session.Store( entity );
sw.Stop();
if (i < 3)
Console.WriteLine( "Stored '{0}' in {1} ms.", entity.Name, sw.ElapsedMilliseconds );
}
sw.Reset();
sw.Start();
session.SaveChanges();
sw.Stop();
Console.WriteLine( "Saved changes in {0} ms.", sw.ElapsedMilliseconds );
}
}
sw.Reset();
sw.Start();
using( var session = store.OpenSession() )
{
sw.Stop();
Console.WriteLine();
Console.WriteLine( "Opened EntityA session in {0} ms.", sw.ElapsedMilliseconds );
sw.Reset();
sw.Start();
var entities = session.Query<EntityA>().ToArray();
sw.Stop();
Console.WriteLine("Queried for all {0} EntityA in {1} ms.", entities.Length, sw.ElapsedMilliseconds);
}
sw.Reset();
sw.Start();
using( var session = store.OpenSession() )
{
sw.Stop();
Console.WriteLine();
Console.WriteLine( "Opened EntityA session (again) in {0} ms.", sw.ElapsedMilliseconds );
sw.Reset();
sw.Start();
var entities2 = session.Query<EntityA>().ToArray();
sw.Stop();
Console.WriteLine( "Queried (again) for all {0} EntityA in {1} ms.", entities2.Length, sw.ElapsedMilliseconds );
}
}
Console.WriteLine();
Console.WriteLine();
Console.WriteLine( "Press ENTER to exit..." );
Console.ReadLine();
}
这会产生以下输出:
Initialized in 6132 ms. Opened session in 3 ms. Stored 'Entity A 08:50:14' in 129 ms. Stored 'Entity A 08:50:15' in 0 ms. Stored 'Entity A 08:50:15' in 0 ms. Saved changes in 29 ms. Opened EntityA session in 0 ms. Queried for all 10 EntityA in 463 ms. Opened EntityA session (again) in 0 ms. Queried (again) for all 10 EntityA in 1 ms.
从这个粗略的例子中,我可以看到:
如何正确查询数据库中某种类型的所有文档(EntityA)? 当然,RavenDB不能要求每个查询都有一个索引吗?特别是没有任何标准的查询?
(注意:我打算使用嵌入在桌面应用程序中的数据库,其中列出所有文档用于显示数据库的内容。)
答案 0 :(得分:5)
以下是三次延误的原因:
初始化延迟
初始化文档存储确实是最昂贵的操作之一。由于您运行的是RavenDB的嵌入式模式,因此它不仅必须建立与数据库的连接,而且实际上还必须启动数据库运行。在我的机器上(2.3Ghz i5笔记本电脑),初始化需要2516ms。
如果您运行的是完整的RavenDB服务器(未嵌入式) - 大部分延迟都是在启动服务器本身时。初始化客户端会明显加快。
这是合理的行为,考虑到IDocumentStore
(无论是嵌入的还是正常的)是要保持为单身。在您的应用程序中应该只有一个这样的实例,它应该在启动时创建并在关闭时处理。
首次延迟商店
由于您没有提供自己的Id
,因此Raven会使用HiLo generation algorithm为您自动生成一个。{1}}。这涉及从数据库中分配一个可分配的ID块,这需要花费很少的时间。后续调用会更快,因为在块用完之前它们不必命中数据库。
如果您提供自己的Id
媒体资源,并使用entities/1
,entities/2
等有效标识符填充它,那么它会更快,因为您会跳过密钥生成。
查询延迟
当您未指定静态索引时,第一次调用.Query<T>()
将尝试创建与查询表达式匹配的动态索引。即使在获取“所有”实体时也是如此,因为它仍然必须使用Raven-Entity-Name
元数据按实体类型进行过滤。 RavenDB中的Collections是一个虚拟的东西,由元数据决定。这些文件实际上是一起生活的 - 因此除了通过元数据查询和过滤之外,没有其他方法可以获取“集合”中的所有项目。
您看到的部分延迟是正在构建的动态索引。然后,对项目进行索引会有延迟。请注意,如果您添加了更多项目(比如几百个),您仍然可以获得相同的延迟,但是您不会收回所有项目。该索引自刚刚创建以来就是陈旧的,而Raven只返回少量索引。在像您这样的测试中,您可能希望明确等待non-stale results。在实际应用程序中,您可能希望预先定义static index。实际上,您可以通过违反静态索引来加快查询速度。延迟将被移动到索引创建时而不是查询时间。
如果你想完全避免使用索引,还有另一种方法:
session.Advanced.LoadStartingWith<EntityA>("EntityAs/");
此方法不使用元数据进行过滤 - 它使用密钥名称本身。它没有查询就直接反对文档存储 - 所以它更快。您需要paginate才能获得大量结果 - 但无论如何您对查询都有同样的担忧。但是使用这种方法,默认的页面大小要小得多(25) - 所以你肯定会很快遇到这种情况。
我希望这能解决您的疑虑。如果你有其他人,请在评论中告诉我。