Lucene 默认不允许在搜索词中使用前导通配符,but this can be enabled和:
QueryParser#setAllowLeadingWildcard(true)
我知道使用前导通配符会阻止 Lucene 使用索引。带有前导通配符的搜索必须扫描整个索引。
如何演示前导通配符查询的性能?什么时候可以用
setAllowLeadingWildcard(true)
? 我已经建立了一个包含 1000 万个文档的测试索引,格式如下:
{ name: random_3_word_phrase }
磁盘索引为360M。
我的测试查询表现良好,但我一直无法实际演示性能问题。例如,查询
name:*ing
在不到 1 秒的时间内生成超过 110 万份文件。查询name:*ing*
同时生成超过 150 万份文件。这是怎么回事?为什么这么慢? 10,000,000 份文件还不够吗?文档是否需要包含多个字段?
最佳答案
取决于你有多少内存,以及内存中有多少 token 索引。
可以在任何旧计算机上快速搜索 360MB 的总索引。 360GB 的索引需要更长的时间...;)
例如,我启动了一个旧的 2GB 索引,并搜索“*e”。
在 8GB 的盒子上,它在 5 秒内返回了 50 万次点击。我在一个只有 1GB 内存的盒子上尝试了相同的索引,大约花了 20 秒。
为了进一步说明,这里有一些通用的 C# 代码,它基本上对 1000 万个随机 3 词短语进行“** E*”类型的搜索。
static string substring = "E";
private static Random random = new Random((int)DateTime.Now.Ticks);//thanks to McAden
private static string RandomString(int size)
{
StringBuilder builder = new StringBuilder();
char ch;
for (int i = 0; i < size; i++)
{
ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));
builder.Append(ch);
}
return builder.ToString();
}
static void FindSubStringInPhrases()
{
List<string> index = new List<string>();
for (int i = 0; i < 10000000; i++)
{
index.Add(RandomString(5) + " " + RandomString(5) + " " + RandomString(5));
}
var matches = index.FindAll(SubstringPredicate);
}
static bool SubstringPredicate(string item)
{
if (item.Contains(substring))
return true;
else
return false;
}
在所有 1000 万个阶段都加载到列表中后,“var matching = index.FindAll(SubstringPredicate);”仍然只需要大约一秒钟的时间。返回超过 400 万次点击。
关键是,内存很快。一旦事情不再适合内存并且您必须开始交换到磁盘,您就会看到性能下降。
关于solr - 了解 Lucene 领先的通配符性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11766351/