2012-03-23 69 views
4

我能够使用嵌入式版本的RavenDb加载几百万个文档,非常漂亮!RavenDb对以百万为单位的文档查询性能的期望

现在我试图查询这些项目,并发现性能不是我所期望的,如果可能的话,几乎是瞬间的,但是在一台相当健壮的机器上可以达到18秒。

下面,你会发现我的朴素代码。

注意:我现在已经解决了这个问题,最终的代码位于帖子的底部。带走的是你需要索引,它们必须是正确的类型,并且需要让RavenDB知道它们。非常满意通过查询引擎返回记录的性能和质量。

谢谢 斯蒂芬

using (var store = new EmbeddableDocumentStore { DataDirectory = @"C:\temp\ravendata" }.Initialize()) 
{ 
    using (IDocumentSession session = store.OpenSession()) 
    { 
     var q = session.Query<Product>().Where(x => x.INFO2.StartsWith("SYS")).ToList(); 
    } 
} 


[Serializable] 
public class Product 
{ 
    public decimal ProductId { get; set; } 
    .... 
    public string INFO2 { get; set; } 
} 

编辑

我加入这个类

public class InfoIndex_Search : AbstractIndexCreationTask<Product> 
{ 
    public InfoIndex_Search() 
    { 
     Map = products => 
      from p in products 
          select new { Info2Index = p.INFO2 }; 

     Index(x => x.INFO2, FieldIndexing.Analyzed); 
    } 
} 

,改变调用方法看起来像这样。

 using (var store = new EmbeddableDocumentStore { DataDirectory = @"C:\temp\ravendata" }.Initialize()) 
     { 
      // Tell Raven to create our indexes. 
      IndexCreation.CreateIndexes(Assembly.GetExecutingAssembly(), store); 

      List<Product> q = null; 
      using (IDocumentSession session = store.OpenSession()) 
      { 
       q = session.Query<Product>().Where(x => x.INFO2.StartsWith("SYS")).ToList(); 
       watch.Stop(); 
      } 
     } 

但我仍然报告18秒做搜索。我错过了什么?在另一个说明中,C:\ temp \ ravendata \ Indexes \ InfoIndex%2fSearch文件夹中有很多新文件,虽然不像插入数据时那么多,但它们在运行此代码后似乎都消失了几次尝试查询。如果IndexCreation.CreateIndexes(Assembly.GetExecutingAssembly(),store);在插入之前调用,只有这样?

EDIT1

使用此代码我能得到查询的一个实例几乎要发生,但似乎你只能运行一次此,这样引出了一个问题。在哪里运行,什么是正确的初始化程序?

store.DatabaseCommands.PutIndex("ProdcustByInfo2", new IndexDefinitionBuilder<Product> 
{ 
    Map = products => from product in products 
         select new { product.INFO2 }, 
    Indexes = 
      { 
       { x => x.INFO2, FieldIndexing.Analyzed} 
      } 
}); 

EDIT2:工作示例

static void Main() 
{ 
    Stopwatch watch = Stopwatch.StartNew(); 

    int q = 0; 
    using (var store = new EmbeddableDocumentStore { DataDirectory = @"C:\temp\ravendata" }.Initialize()) 
    { 
     if (store.DatabaseCommands.GetIndex("ProdcustByInfo2") == null) 
     { 
      store.DatabaseCommands.PutIndex("ProdcustByInfo2", new IndexDefinitionBuilder<Product> 
      { 
       Map = products => from product in products 
            select new { product.INFO2 }, 
       Indexes = { { x => x.INFO2, FieldIndexing.Analyzed } } 
      }); 
     } 
     watch.Stop(); 
     Console.WriteLine("Time elapsed to create index {0}{1}", watch.ElapsedMilliseconds, System.Environment.NewLine); 

     watch = Stopwatch.StartNew();    
     using (IDocumentSession session = store.OpenSession()) 
     { 
      q = session.Query<Product>().Count(); 
     } 
     watch.Stop(); 
     Console.WriteLine("Time elapsed to query for products values {0}{1}", watch.ElapsedMilliseconds, System.Environment.NewLine); 
     Console.WriteLine("Total number of products loaded: {0}{1}", q, System.Environment.NewLine); 

     if (q == 0) 
     { 
      watch = Stopwatch.StartNew(); 
      var productsList = Parsers.GetProducts().ToList(); 
      watch.Stop(); 
      Console.WriteLine("Time elapsed to parse: {0}{1}", watch.ElapsedMilliseconds, System.Environment.NewLine); 
      Console.WriteLine("Total number of items parsed: {0}{1}", productsList.Count, System.Environment.NewLine); 

      watch = Stopwatch.StartNew(); 
      productsList.RemoveAll(_ => _ == null); 
      watch.Stop(); 
      Console.WriteLine("Time elapsed to remove null values {0}{1}", watch.ElapsedMilliseconds, System.Environment.NewLine); 
      Console.WriteLine("Total number of items loaded: {0}{1}", productsList.Count, System.Environment.NewLine); 

      watch = Stopwatch.StartNew(); 
      int batch = 0; 
      var session = store.OpenSession(); 
      foreach (var product in productsList) 
      { 
       batch++; 
       session.Store(product); 
       if (batch % 128 == 0) 
       { 
        session.SaveChanges(); 
        session.Dispose(); 
        session = store.OpenSession(); 
       } 
      } 
      session.SaveChanges(); 
      session.Dispose(); 
      watch.Stop(); 
      Console.WriteLine("Time elapsed to populate db from collection {0}{1}", watch.ElapsedMilliseconds, System.Environment.NewLine); 
     } 

     watch = Stopwatch.StartNew(); 
     using (IDocumentSession session = store.OpenSession()) 
     { 
      q = session.Query<Product>().Where(x => x.INFO2.StartsWith("SYS")).Count(); 
     } 
     watch.Stop(); 
     Console.WriteLine("Time elapsed to query for term {0}{1}", watch.ElapsedMilliseconds, System.Environment.NewLine); 
     Console.WriteLine("Total number of items found: {0}{1}", q, System.Environment.NewLine); 
    } 
    Console.ReadLine(); 
} 
+0

你有一个涵盖INFO2的指数吗? – 2012-03-23 16:38:20

+0

我现在在做什么..旅程是多么有趣,但非常值得。 – 2012-03-24 14:24:38

回答

6

首先,你必须覆盖INFO2的指数?

其次,看到丹尼尔郎咸平的“搜索在RavenDB字符串属性”此处的博客文章:

http://daniellang.net/searching-on-string-properties-in-ravendb/

如果有帮助,这里就是我创建的索引:

public class LogMessageCreatedTime : AbstractIndexCreationTask<LogMessage> 
{ 
    public LogMessageCreatedTime() 
    { 
     Map = messages => from message in messages 
          select new { MessageCreatedTime = message.MessageCreatedTime }; 
    } 
} 

又如何我在运行时添加了它:

private static DocumentStore GetDatabase() 
{    
    DocumentStore documentStore = new DocumentStore();    

    try 
    { 
     documentStore.ConnectionStringName = "RavenDb";     
     documentStore.Initialize(); 

     // Tell Raven to create our indexes. 
     IndexCreation.CreateIndexes(typeof(DataAccessFactory).Assembly, documentStore); 
    } 
    catch 
    { 
     documentStore.Dispose(); 
     throw; 
    } 

    return documentStore; 
} 

就我而言,我不必明确查询索引;当我正常查询时才使用它。

+1

是的,我昨天在另一篇文章中遇到丹尼尔,然后搜索了一些东西,他的网站出现了。阅读大部分乌鸦标记的帖子。除了缺少文档之外,外卖是自动完成索引的,而不是猜测。 – 2012-03-23 17:29:57

+0

有动态索引,它是根据用途自动创建的,但这些实际上只是一个权宜之计,或者对于小型数据库(在我看来)。他们让你快速启动并使用安全的默认设置。 – 2012-03-23 17:40:52

+0

我在我的答案中添加了一些代码。希望能帮助到你。 – 2012-03-23 17:56:02

0

正如Bob所暗示的那样,您应该确保您在Raven中创建了涵盖您打算查询的字段的索引。

乌鸦非常快,可以让你走很长的路,而不需要做太多。 然而,一旦你开始进入大文件号码,或者需要非默认的东西,你会发现你需要静态索引。

在Raven中有很多关于设置和使用索引的示例。

+0

谢谢。你能否指点我一些文档来说明正确的索引创建和后续查询这些索引? – 2012-03-23 17:33:22

+1

我不确定'官方'文档(我在平板电脑上atm,所以看起来有点困难),但我写了一篇博客文章,演示在Raven http://will.hughesfamily.net上创建和安装索引。 .au/20101212/ravendb-map-reduce-indexes-and-how-to-install-them/- 希望有所帮助(只需忽略'reduce'位) – 2012-03-23 17:45:20

+0

另外,Bob链接的博客文章给出了一个很好的例子的Map语句,以及如何使用它们。 – 2012-03-23 17:46:45