2010-07-21 11 views
7

Ho scritto un piccolo ciclo che ha aggiunto 10.000 documenti nell'IndexWriter e ci è voluto per sempre a farlo.Lucene IndexWriter lento per aggiungere documenti

C'è un altro modo per indicizzare grandi volumi di documenti?

Chiedo, perché quando questo va in diretta deve caricare in 15.000 record.

L'altra domanda è: come impedire di dover caricare nuovamente tutti i record quando si riavvia l'applicazione Web?

Modifica

Ecco il codice che ho usato;

for (int t = 0; t < 10000; t++){ 
    doc = new Document(); 
    text = "Value" + t.toString(); 
    doc.Add(new Field("Value", text, Field.Store.YES, Field.Index.TOKENIZED)); 
    iwriter.AddDocument(doc); 
}; 

Edit 2

 Analyzer analyzer = new StandardAnalyzer(); 
     Directory directory = new RAMDirectory(); 

     IndexWriter iwriter = new IndexWriter(directory, analyzer, true); 

     iwriter.SetMaxFieldLength(25000); 

poi il codice per aggiungere i documenti, poi;

 iwriter.Close(); 
+1

Quanto tempo è durato per sempre? –

+0

ci sono voluti dai 2,5 ai 3 minuti. È prevedibile? – griegs

+0

Dovrei aggiungere che i documenti contenevano un singolo campo e che il campo aveva "valore" + t.toString() come valore. Quindi molto piccolo – griegs

risposta

5

Proprio il controllo, ma non hanno ottenuto il debugger quando si esegue l'avete?

Questo influisce notevolmente sulle prestazioni quando si aggiungono documenti.

Sulla mia macchina (Lucene 2.0.0.4):

Costruito con x86 bersaglio piattaforma:

  • No debugger - 5,2 secondi

  • debugger - 113,8 secondi

Costruito con target di piattaforma x64:

  • No debugger - 6,0 secondi

  • debugger - 171,4 secondi

ruvida esempio di salvare e caricare un indice da e verso un RAMDirectory:

const int DocumentCount = 10 * 1000; 
const string IndexFilePath = @"X:\Temp\tmp.idx"; 

Analyzer analyzer = new StandardAnalyzer(); 
Directory ramDirectory = new RAMDirectory(); 

IndexWriter indexWriter = new IndexWriter(ramDirectory, analyzer, true); 

for (int i = 0; i < DocumentCount; i++) 
{ 
    Document doc = new Document(); 
    string text = "Value" + i; 
    doc.Add(new Field("Value", text, Field.Store.YES, Field.Index.TOKENIZED)); 
    indexWriter.AddDocument(doc); 
} 

indexWriter.Close(); 

//Save index 
FSDirectory fileDirectory = FSDirectory.GetDirectory(IndexFilePath, true); 
IndexWriter fileIndexWriter = new IndexWriter(fileDirectory, analyzer, true); 
fileIndexWriter.AddIndexes(new[] { ramDirectory }); 
fileIndexWriter.Close(); 

//Load index 
FSDirectory newFileDirectory = FSDirectory.GetDirectory(IndexFilePath, false); 
Directory newRamDirectory = new RAMDirectory(); 
IndexWriter newIndexWriter = new IndexWriter(newRamDirectory, analyzer, true); 
newIndexWriter.AddIndexes(new[] { newFileDirectory }); 

Console.WriteLine("New index writer document count:{0}.", newIndexWriter.DocCount()); 
+0

+1, grazie per questo guarderò stasera. ho il sospetto che possa essere il debugger ora che ne parli. grazie per il tuo aiuto – griegs

+0

grazie per il tuo aiuto. non sto ottenendo i bei tempi che sei. il mio è a 16sec che è accettabile penso. Penso che sia fino al mio hardwear ora. – griegs

10

È dovrebbe fare in questo modo per ottenere le migliori prestazioni.sulla mia macchina io sono l'indicizzazione 1000 documento in 1 secondo

1) Si dovrebbe riutilizzare (Documento, Field) non creando ogni volta che si aggiunge un documento come questo

private static void IndexingThread(object contextObj) 
{ 
    Range<int> range = (Range<int>)contextObj; 
    Document newDoc = new Document(); 
    newDoc.Add(new Field("title", "", Field.Store.NO, Field.Index.ANALYZED)); 
    newDoc.Add(new Field("body", "", Field.Store.NO, Field.Index.ANALYZED)); 
    newDoc.Add(new Field("newsdate", "", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS)); 
    newDoc.Add(new Field("id", "", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS)); 

    for (int counter = range.Start; counter <= range.End; counter++) 
    { 
     newDoc.GetField("title").SetValue(Entities[counter].Title); 
     newDoc.GetField("body").SetValue(Entities[counter].Body); 
     newDoc.GetField("newsdate").SetValue(Entities[counter].NewsDate); 
     newDoc.GetField("id").SetValue(Entities[counter].ID.ToString()); 

     writer.AddDocument(newDoc); 
    } 
} 

Dopo di che è possibile utilizzare threading e rompere il vostro grande collezione in quelle più piccole, e utilizzare il codice di cui sopra per ogni sezione per esempio se si dispone di 10.000 documenti è possibile creare 10 Discussione utilizzando ThreadPool e mangimi ogni sezione per un thread per l'indicizzazione

Poi si otterrà la la prestazione migliore.

+0

+1 @Ehsan, grazie per questo. Ci proverò oggi. – griegs