2013-02-09 36 views
4

我想学习如何使用RavenDB,并为此创建了一个基本示例。 看起来初始化商店和查询需要很长时间!如何优化用于检索所有文档的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需要每个查询的索引?特别是没有任何标准的查询?

(注:我打算使用嵌入在桌面应用程序,其中列出了所有文件,用于显示数据库中的内容DB)

+0

这样的“为什么”这样的问题的答案通常很难找到,难以应用(因此,“不具有建设性”)。不要问为什么它是这样的,你可能想要编辑来问你需要在你的代码中做什么样的事情来优化性能。 – 2013-02-09 08:08:07

+0

够公平的。举一个基本的例子,我的目的是作为一个解释性答案,比如“你使用错了,因为......”而不是简单的是/否的答案,例如“是的,使用索引”,它不能解释“为什么”。但你的观点是合理的。我会尝试重新说明我的问题! – Reyhn 2013-02-09 08:13:44

回答

4

这里有三个延误的原因:

初始化延迟
初始化文档存储确实是最昂贵的操作之一。由于您正在运行RavenDB的嵌入模式,因此它不仅必须建立与数据库的连接,还必须启动数据库以及运行。在我的机器上(2.3Ghz i5笔记本电脑),初始化需要2516ms。

如果您正在运行完整的RavenDB服务器(不是嵌入式) - 大部分延迟都是在启动服务器时。初始化客户端将显着加快。

这是合理的行为,考虑到IDocumentStore(无论是嵌入式的还是普通的)是为了保持单身。应用程序中应该只有一个实例,它应该在启动时创建并在关闭时处理。

第一家店延迟
因为你不提供自己的Id,乌鸦是自动生成使用其HiLo generation algorithm一个给你。这涉及从数据库分配一个可分配的ID块,这需要很少的时间。随后的调用将会更快,因为在块被用完之前,他们不必击中数据库。

如果你提供你自己的财产Id,并用有效的标识符填充诸如entities/1entities/2等 - 那么这将是更快,因为你会跳过密钥生成。

查询延迟
第一次调用.Query<T>()当你不指定一个静态指标将尝试创建一个查询表达式匹配的动态指标。即使获得“所有”实体,情况也是如此,因为它仍然必须使用元数据过滤实体类型。 RavenDB中的Collections是一个虚拟的东西,由元数据决定。这些文档实际上是一起生活的 - 所以没有其他方式可以获取“集合”中的所有项目,而不是通过元数据进行查询和过滤。

您看到的部分延迟是正在构建的动态索引。然后,这些项目将被编入索引。请注意,如果您添加了更多项目(比如说几百项),那么您仍然会得到相同的延迟,但是您不会收回所有项目。该索引自创建以来就是陈旧的了,而乌鸦只会返回其中的一小部分。在像你这样的测试中,你可能想要明确地等待non-stale results。在实际应用中,您可能需要预先定义static index。事实上,您可以通过违反静态索引来加快查询速度。延迟将被移至索引创建时间而不是查询时间。

如果你想避免使用索引可言,还有另一种方式:

session.Advanced.LoadStartingWith<EntityA>("EntityAs/"); 

这种方法不使用元数据过滤 - 它使用的键名本身。它直接与文档存储不匹配 - 因此速度更快。您将需要paginate以获得大量结果 - 但无论如何,您仍然有同样的疑虑。但是用这种方法,默认的页面尺寸要小得多(25) - 所以你肯定会很快遇到这个问题。

我希望这能解答您的疑虑。如果您有其他人,请在评论中告诉我。

+0

非常好!这些答案正是我所希望的,还有更多!他们应该把你放在RavenDB文档中! (: 谢谢!! – Reyhn 2013-02-10 08:18:13