我有一个性能敏感的任务,我正在考虑在内存中存储大约100,000个项目的所有对象。 (持久于ms sql,但在内存中复制以提高复杂的搜索性能)
按键搜索工作得足够快,但按文字搜索,例如。包含相对较慢 - 每个查询大约需要30毫秒,如下所示:
IEnumerable<Product> result =
products.Where(p =>
p.Title.Contains(itemnames[rnd.Next(itemnames.Length)]));
我已经尝试过使用内存数据库db4o,但性能更差 - 每次搜索100K项目约1.5秒。
为了不审查每个对象标题并更快地执行此操作,有哪些选项?
我可以用什么内存数据库来解决这个问题?
答案 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)。