在C#内存中实现文本索引

时间:2011-02-27 00:37:42

标签: caching memory

我有一个性能敏感的任务,我正在考虑在内存中存储大约100,000个项目的所有对象。 (持久于ms sql,但在内存中复制以提高复杂的搜索性能)

按键搜索工作得足够快,但按文字搜索,例如。包含相对较慢 - 每个查询大约需要30毫秒,如下所示:

IEnumerable<Product> result =
   products.Where(p =>
   p.Title.Contains(itemnames[rnd.Next(itemnames.Length)]));

我已经尝试过使用内存数据库db4o,但性能更差 - 每次搜索100K项目约1.5秒。

为了不审查每个对象标题并更快地执行此操作,有哪些选项?

我可以用什么内存数据库来解决这个问题?

4 个答案:

答案 0 :(得分:2)

您是否可以选择更改存储产品的数据结构?加速包含搜索的一种方法是在Product.Title中存储每个可能的Dictionary<string, List<Product>>子字符串。这将允许您的搜索为O(1)而不是O(n)。

您可以像这样生成每个子字符串:

public static IEnumberable<string> AllSubstrings(this string value)
{
    int index = 0;
    while(++index <= value.Length)
    {
        yield return value.Substring(0, index);
    }

    index = 0;
    while(++index <= value.Length - 1)
    {
        yield return value.Substring(index);
    }
}

然后你可以这样填充你的字典:

var titleIndex = new Dictionary<string, List<Product>>();

foreach(Product product in products)
{
    foreach(string substring in product.Title.AllSubstrings())
    {
        if(titleIndex.ContainsKey(substring))
        {
            index[substring].Add(product);
        }
        else
        {
            index[substring] = new List<Product> { product };
        }
    }
}

最后,你执行搜索:

string searchString = itemnames[rnd.Next(itemnames.Length)];

if(titleIndex.ContainsKey(searchString))
{
    List<Product> searchResults = titleIndex[searchString];
}

注意:正如您可能已经猜到的那样,像这样存储您的数据会占用更多的CPU时间并使用更多的RAM。

答案 1 :(得分:0)

尝试使用Sql Server全文搜索:http://msdn.microsoft.com/en-us/library/ms142571.aspx
它可能比您的示例中的顺序搜索更快。

答案 2 :(得分:0)

如果您确实需要搜索包含的单词而不是真正的任何包含文本,那么在内存中创建索引。创建一个词典并为标题中的每个单词添加一个条目到词典。然后,您可以通过单个单词快速查找。

另一种选择是将数据加载到SQLite内存数据库中,并使用内置的全文搜索引擎进行搜索。

答案 3 :(得分:0)

我会尝试SQLite,因为它嵌入了全文索引(FTS3)。