我正在尝试构建一个Lucene Serializer类,它将使用DataMember修饰的属性序列化/反序列化对象(类),以及一个特殊属性,其中包含有关如何在Lucene索引中存储属性/字段的说明。 / p>
当我需要通过某个键/值对检索单个对象时,该类工作正常。 但是我注意到,如果有时候我需要检索所有项目,并且据说有100,000个文档 - 那么MySQL会做到这一点〜大约快10倍......出于某种原因......
请您查看此代码(Lucene专家)并提出任何与性能相关的改进建议吗?
public IEnumerable<T> LoadAll()
{
IndexReader reader = IndexReader.Open(this.PathToLuceneIndex);
int itemsCount = reader.NumDocs();
for (int i = 0; i < itemsCount; i++)
{
if (!reader.IsDeleted(i))
{
Document doc = reader.Document(i);
if (doc != null)
{
T item = Deserialize(doc);
yield return item;
}
}
}
if (reader != null) reader.Close();
}
private T Deserialize(Document doc)
{
T itemInstance = Activator.CreateInstance<T>();
foreach (string fieldName in fieldTypes.Keys)
{
Field myField = doc.GetField(fieldName);
//Not every document may have the full collection of indexable fields
if (myField != null)
{
object fieldValue = myField.StringValue();
Type fieldType = fieldTypes[fieldName];
if (fieldType == typeof(bool))
fieldValue = fieldValue == "1" ? true : false;
if (fieldType == typeof(DateTime))
fieldValue = DateTools.StringToDate((string)fieldValue);
pF.SetValue(itemInstance, fieldName, fieldValue);
}
}
return itemInstance;
}
提前谢谢!
答案 0 :(得分:1)
以下是一些提示:
首先,不要使用IndexReader.Open(string path)
。它不仅会在Lucene.net的下一个主要版本中删除,它通常不是您的最佳选择。当你让Lucene为你生成目录时,实际上会调用大量不必要的代码。我建议:
var dir = new SimpleFSDirectory(new DirectoryInfo(path));
var reader = IndexReader.Open(dir, true);
你也应该像我上面那样做,并且如果你不是绝对需要写它,那么只打开IndexReader
,因为它在多线程环境中会更快。
如果您知道索引的大小不超过内存容量(即小于500-600 MB且未压缩),则可以使用RAMDirectory
代替。这会将整个索引加载到内存中,如果您将索引保留在磁盘上,则可以绕过大部分昂贵的IO操作。它应该极大提高你的速度,特别是如果你使用下面的其他建议。
如果索引太大而无法容纳在内存中,您需要将索引拆分为块(即每n MB一个索引)或者继续从磁盘读取索引。
另外,我知道yield return
中你不能try...catch
,但你可以try...finally
,我建议你将LoadAll()
中的逻辑包装成一个try...finally
IndexReader reader = null;
try
{
//logic here...
}
finally
{
if (reader != null) reader.Close();
}
,例如
string fieldValue = myField.StringValue();
现在,当谈到你的实际Deserialize代码时,你可能以几乎最快的方式完成它,除了你在不需要的时候装箱。 Lucene仅将字段存储为byte []数组或字符串。因为你正在调用字符串值,所以你知道它总是一个字符串,并且只有在绝对必要时才必须将其打包。将其更改为:
{{1}}
这至少有时可以节省你的小拳击费用。 (真的,不多)
关于拳击的主题,我们正在研究lucene的一个分支,你可以从SVN中提取,它将Lucene的内部结构从使用装箱容器(ArrayLists,非泛型列表和HashTables)更改为使用泛型的版本以及更多.net友好的东西。这是2.9.4g branch。正如我们所愿说的那样.Net'。我们尚未正式对其进行基准测试,但开发人员测试显示,在某些情况下,它比旧版本快了约200%。
另外要记住的是,Lucene作为一个搜索引擎很棒,你可能会发现在某些情况下,它可能无法与MySQL相提并论。但实际上,唯一可以确定的方法就是测试并尝试找到性能瓶颈,就像我上面提到的一些瓶颈一样。
希望有所帮助!如果您有任何疑问,请不要忘记Lucene.Net邮件列表(lucene-net-dev@lucene.apache.org)。我和其他提交者通常很快回答问题。