大規模な Lucene インデックスを作成しています。挿入する各ドキュメントは、挿入する前に少し「まとめる」必要があります。データベースからすべてのドキュメントを読み取り、それらをインデックスに挿入しています。Lucene を使用すると、いくつかの異なるインデックスを作成し、後でそれらをマージできるため、次のように考えました。
// we'll use a producer/consumer pattern for the job
var documents = new BlockingCollection<Document>();
// we'll have a pool of index writers (each will create its own index)
var indexWriters = new ConcurrentBag<IndexWriter>();
// start filling the collection with documents
Task writerTask = new Task(() => {
foreach(document in database)
documents.Add(document);
domains.CompleteAdding();
}, TaskCreationOptions.LongRunning);
writerTask.Start();
// iterate through the collection, obtaining index writers from the pool and
// creating them when necessary.
Parallel.ForEach(documents.GetConsumingEnumerable(token.Token), document =>
{
IndexWriter writer;
if(!indexWriters.TryTake(out writer))
{
var dirInfo = new DirectoryInfo(string.Concat(_indexPath, "\\~", Guid.NewGuid().ToString("N")));
dirInfo.Create();
var dir = FSDirectory.Open(dirInfo);
var indexWriter = new IndexWriter(dir, getAnalyzer(), true, IndexWriter.MaxFieldLength.UNLIMITED);
}
// prepare and insert the document into the current index
WriteDocument(writer, document);
indexWriters.Add(writer); // put the writer back in the pool
});
// now get all of the writers and merge the indexes together...
私が一時停止した唯一の懸念は、最初から最適な数のスレッドを作成するよりも、反復ごとにプールから IndexWriter をプルする (そして最後に戻す) ほうが効率が悪い可能性があることでした。 ConcurrentBag は非常に効率的で、処理のオーバーヘッドが非常に低くなります。
私の解決策は大丈夫ですか?それとも、より良い解決策を求めて叫びますか?
アップデート:
いくつかのテストの後、データベースからの読み込みは、実際のインデックス作成よりも少し遅いと思います。また、1 つのスレッドしか使用できず、16 のインデックスと約 170 万のドキュメントをマージしていたため、最終的なインデックスのマージも遅くなります。それでも、私は元の質問についての考えを受け入れています。