2016-08-24 2 views
1

私はApache Luceneを使用しています。私のデータベースは約3GBです。Luceneでインデックスを更新するには

Luceneを初めて使用してインデックスを作成するときは、約25分かかります。しかし、私はそれを使用しているたびに更新されるような私のアプリケーションが欲しいです。

どのようにこれらのことを行うことができます私のインデックスは毎回更新することができますし、更新するのにかかる時間は短くなりますか?

データベースの変更は非常に少ないですが、データベースの新しいエントリにはインデックスを付ける必要があります。

Directory directory = new SimpleFSDirectory(INDEX_DIRECTORY); 
     //Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_36); 
     SimpleAnalyzer analyzer = new SimpleAnalyzer(Version.LUCENE_36); 
      IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LUCENE_36, analyzer); 
      indexWriterConfig.setOpenMode(IndexWriterConfig.OpenMode.CREATE); 
      IndexWriter iWriter = new IndexWriter(FSDirectory.open(indexDirNEW), indexWriterConfig); 
     IndexWriter iWriter = new IndexWriter(directory, analyzer, true,MaxFieldLength.UNLIMITED); 



     int count = 0; 
     while(rs.next()) { 
      Document doc = new Document(); 
      doc.add(new Field("NAME", rs.getString("NAME")==null?"":rs.getString("NAME"), Field.Store.YES, Field.Index.ANALYZED)); 
      doc.add(new Field("CUSTOMER", rs.getString("CUSTOMER")==null?"":rs.getString("CUSTOMER"), Field.Store.YES, Field.Index.ANALYZED)); 
      iWriter.addDocument(doc); 
      count++; 
     } 

     System.out.println(count+" record indexed"); 
     iWriter.optimize(); 
     iWriter.commit(); 
     iWriter.close(); 
+0

最も明らかなスピードアップは、optimize()を呼び出さないことです。あなたの実行時間がどこに費やされているかを見るためにコードをプロファイリングしましたか? – sisve

答えて

1

まず第一に、私はあなたがLuceneのアップグレードをお勧めしたいです。 3.6以降、大幅なパフォーマンスの向上が見られました。 (例えば、Mike McCandless writes about a 256% speedup in indexing using Lucene 4.0 features)。


これ以外にも、ループ内のコードを最適化することで多くの利益を得ることができます。実際に新しい文書やフィールドをインスタンス化する必要はなく、値を更新するだけで済みます。

インデックスで列を参照する代わりに、名前ではなくビットで保存します。また、ResultSet.getStringへの複数の呼び出しを排除して、それらを文字列に代入することもできます。あなたのケースでどれだけ重要であるかが分かりません。

final int NAME_INDEX = 1; 
final int CUSTOMER_INDEX = 2; 

//Setup document 
Document doc = new Document(); 
Field nameField = new Field("NAME", "", Field.Store.YES, Field.Index.ANALYZED); 
doc.add(nameField); 
Field customerField = new Field("CUSTOMER", "", Field.Store.YES, Field.Index.ANALYZED); 
doc.add(customerField); 

int count = 0; 
while(rs.next()) { 
    String name = rs.getString(NAME_INDEX); 
    String customer = rs.getString(CUSTOMER_INDEX); 
    nameField.setValue(name == null ? "":name); 
    customerField.setValue(customer == null ? "":customer); 
    iWriter.addDocument(doc); 
    count++; 
} 

いくつかのテストを行っていますが、これらの調整により、テストが完了するまでに約20%の時間が節約されたようです。些細なことではありませんが、Luceneをアップグレードすることで、さらに多くのことが得られます。

また、十分なメモリがあることを傷つけることもできませんでした。すべてのデータをインデックス化して最適化しようとしている間にスラッシングを開始すると、パフォーマンスはフロアを通過します。

ここで調べる価値のあるヒントがいくつかあります:How to make searching faster

0

あなたのLuceneインデックスコードはDBを使用してメインアプリケーションから切断され、いくつかの低い時間の間に、別のジョブとして実行されている場合は、あなたの仕事に二つのモードを導入する必要がある - 増分モードフル・インデックスモード

私はそのような設定を1つ持っています。基本的には、設定パラメータとプロパティを介して設定可能なインデックスを付けるテーブルデータを選択するSQLクエリを作成しました。 DB &インデックスが同期していない場合(ジョブの実行頻度に依存する)、および手動ジョブパラメータの変更。サーチャーアプリケーションでインクリメンタルインデックスを最初に行うことで、同期外の問題を減らそうとしています。

2つ目のアプローチは、明らかに、アプリケーションによってDBを更新するたびにインデックスコードを開始することです。

私の場合、lucene searcherアプリケーションはDBを更新するので、更新されたレコードに関するすべての詳細を知っているので、そこからluceneインデックスをすぐに更新します。

ここに掲載されている改善のほとんどは、How to make indexing fasterに実装されています。いくつかの提案は、最近のluceneのバージョンには関係ありません。

また、インデックス作成がオーバーしているかどうかを確認してください。サーチャーアプリケーションでは不要なインデックスデータ。

SQLの選択クエリをリエンジニアリングすることは、2億回以上の行があり、データを高速に選択することがコア領域であったため、私にとっては別の改善領域でした。

DBの使用接続プールと複数のJavaスレッドから同じライターインスタンスを使用すると、さらに高速化できました(lucene writerはスレッドセーフなので)。私はDB接続とスレッドの数を設定可能に保ちます。だから私は複数のスレッドに私のインデックスの負荷を配布します。また、私は大量のデータをコミットしますが、開いて閉じるライターは一度だけです。

femtoRgonの回答とコメントに他の提案が掲載されています。私の経験によれば、改善は徐々に進行し、最初のショットではすべてを達成することはできません。

関連する問題