Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/274.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/gwt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 具有频繁更新索引的FieldCache_C#_Java_.net_Lucene_Lucene.net - Fatal编程技术网

C# 具有频繁更新索引的FieldCache

C# 具有频繁更新索引的FieldCache,c#,java,.net,lucene,lucene.net,C#,Java,.net,Lucene,Lucene.net,嗨 我有lucene索引,它经常用新记录更新,我的索引中有5000000条记录,我正在使用FieldCache缓存我的一个数字字段。但在更新索引后,需要时间再次重新加载FieldCache(我重新加载缓存,因为文档中说DocID不可靠),因此如何通过只向FieldCache添加新添加的DocID来最小化此开销,因为此功能在我的应用程序中变成了瓶颈 IndexReader reader = IndexReader.Open(diskDir); int[] dateArr = FieldCache


我有lucene索引,它经常用新记录更新,我的索引中有5000000条记录,我正在使用FieldCache缓存我的一个数字字段。但在更新索引后,需要时间再次重新加载FieldCache(我重新加载缓存,因为文档中说DocID不可靠),因此如何通过只向FieldCache添加新添加的DocID来最小化此开销,因为此功能在我的应用程序中变成了瓶颈


IndexReader reader = IndexReader.Open(diskDir);
int[] dateArr = FieldCache_Fields.DEFAULT.GetInts(reader, "newsdate"); // This line takes 4 seconds to load the array
dateArr = FieldCache_Fields.DEFAULT.GetInts(reader, "newsdate"); // this line takes 0 second as we expected
// HERE we add some document to index and we need to reload the index to reflect changes

reader = reader.Reopen();
dateArr = FieldCache_Fields.DEFAULT.GetInts(reader, "newsdate"); // This takes 4 second again to load the array

我想要一种机制,通过只向数组中的索引添加新添加的文档来最小化这一时间。有一种技术是这样的
为了提高性能,但它仍然加载我们已经拥有的所有文档,我认为如果我们找到一种只向数组中添加新添加的文档的方法,就没有必要重新加载所有文档。您需要创建一个后台线程来构造
indexsearch
实例,每隔一段时间一个实例。继续使用当前的
IndexSearcher
实例,直到后台线程中的新实例就绪。然后把新的换成当前的。从第一次打开索引时起,每个实例都充当索引的快照。请注意,
FieldCache
的内存开销加倍,因为您需要同时在内存中使用两个实例。发生这种情况时,您可以安全地写入
IndexWriter

如果您需要,您可以更进一步,使索引更改立即可用于搜索,尽管这可能会变得棘手。您需要将
RAMDirectory
与上面的每个快照实例相关联,以将更改保留在内存中。然后创建第二个
IndexWriter
,指向该
RAMDirectory
。对于每次索引写入,您都需要同时写入
IndexWriter
实例。对于搜索,您将在
RAMDirectory
和磁盘上的普通索引中使用
multisearch
。一旦与其耦合的
索引搜索器
不再使用,则可以丢弃
RAMDirectory
。我在这里对一些细节进行了润色,但这是总体思路


希望这有帮助。

FieldCache使用弱引用来索引读卡器作为缓存的键。(通过调用未过时的
IndexReader.GetCacheKey
)使用
FSDirectory
标准调用
IndexReader.Open
将使用一个读卡器池,每个段一个

您应该始终将最里面的读取器传递给FieldCache。查看
ReaderUtil
,获取一些帮助工具,以检索文档所包含的单个阅读器。文档ID不会在一个段内更改,当将其描述为不可预测/易变时,它们的意思是它将在两个索引提交之间更改。删除的文档可能会被删除,段可能会被合并,这样的操作也会被删除

提交需要从磁盘中删除段(合并/优化),这意味着新读卡器将不会有池段读卡器,垃圾收集将在所有旧读卡器关闭后立即删除它

永远不要调用
FieldCache.PurgeAllCaches()
。这是为了测试,而不是生产使用

新增2011-04-03;使用子读取器的示例代码

var directory = FSDirectory.Open(new DirectoryInfo("index"));
var reader = IndexReader.Open(directory, readOnly: true);
var documentId = 1337;

// Grab all subreaders.
var subReaders = new List<IndexReader>();
ReaderUtil.GatherSubReaders(subReaders, reader);

// Loop through all subreaders. While subReaderId is higher than the
// maximum document id in the subreader, go to next.
var subReaderId = documentId;
var subReader = subReaders.First(sub => {
    if (sub.MaxDoc() < subReaderId) {
        subReaderId -= sub.MaxDoc();
        return false;
    }

    return true;
});

var values = FieldCache_Fields.DEFAULT.GetInts(subReader, "newsdate");
var value = values[subReaderId];
var directory=FSDirectory.Open(新目录信息(“索引”);
var reader=IndexReader.Open(目录,只读:true);
var documentId=1337;
//抓取所有子阅读器。
var subReaders=新列表();
ReaderUtil.GatherSubReaders(子读取器,读取器);
//循环遍历所有子读取器。而子读取器ID高于
//子读取器中的最大文档id,转到下一步。
var subReaderId=documentId;
var subReader=subReaders.First(sub=>{
if(sub.MaxDoc()
假设您在磁盘上的FSDirectory中有1000条记录,并使用FieldCache加载它,并且您在RAMDirectory中有新的10条记录,正如您上面解释的那样,因此我们有两个ID为0的文档,…,10因为每个目录都有自己的docID,我无法创建具有唯一docID的集成FieldCache,在添加10次记录后,我还优化了索引。在这种情况下,docID可能会改变。第二部分的技巧是,您将在
FSDirectory
RAMDirectory
之间使用
MultiSearcher
,这样
FSDirectory
RAMDirectory
开始更改之前就被打开了。因此,在它看来,给定ID的两个文档中只有一个存在。当您执行搜索时,
MultiSearcher
处理合并这两个搜索。除非您在搜索之外使用
FieldCache
?不过,我还是从第一部分开始,在后台打开第二个
indexsearch
(或
IndexReader
)实例,让它构建
FieldCache
,然后将其替换掉。是的,我想在CustomScoreQueryTanks中的搜索之外使用FieldCache,但我想确保如果我将新文档添加到索引中,该文档的文档id在合并或优化时不会更改,因为如果它更改,则上述解决方案无法满足我的需要,因为我只想向FieldCache提供新添加的文档,以防止使用FieldCache再次加载所有文档,如果我能确保在合并/优化过程中哪个段读取器保持完整,那么我肯定可以根据您的解决方案加载它们,并重新加载其他段读取器值,这会逐渐提高性能,但仍然不理想,因为我希望合并/优化后读取器在技术上保持完整,它们也被淘汰,并被新创建的细分市场所取代。您能提供一些在当前设置中遇到问题的代码示例吗