2011-10-08 7 views
5

Siamo su Sitecore 6.4 e stiamo utilizzando il modulo di ricerca avanzata di origine condivisa e stiamo assistendo a un grande degrado delle prestazioni di ricerca del sito quando il processo di reindicizzazione di Sitecore inizia e aggiorna le modifiche al database web.Rendimento dell'indice Sitecore durante la reindicizzazione e personalizzato IndexingProvider

Quando iniziamo a pubblicare un intero sito, il gestore di indicizzazione preleva le modifiche e elabora i record della cronologia, che a sua volta reindicizza ogni elemento che è stato interessato. Poiché questo sta accadendo per articolo, puoi vedere l'indice di Lucene sul disco che cambia mentre guardi la directory (il numero di file cresce e cambia mentre lo guardi).

Se si tenta di eseguire ricerche sul sito Web pubblico quando ciò accade, la ricerca può richiedere notevolmente più tempo per essere completata; e sotto carichi pesanti può richiedere fino a 15 secondi più a lungo fino al termine del processo di indicizzazione.

posso vedere questo processo è controllato dalla classe IndexingProvider. Esiste un modo per scavalcare questa classe e implementare la nostra?

Abbiamo esaminato la logica di ricerca e possiamo vedere che un oggetto IndexSearchContext viene creato ogni volta che viene richiesta una ricerca, che a sua volta crea un nuovo IndexSearcher. Abbiamo cambiato un po 'la logica in modo che l'IndexSearchContext è conservato come un singlton, che ovviamente significa che più richieste possono essere serviti dallo stesso Lucene IndexSearcher. Ciò ha drasticamente ridotto il consumo di memoria poiché si consiglia di utilizzare lo stesso searher per aumentare le prestazioni.

Tuttavia, in tal modo, le modifiche all'indice non verranno rilevate fino a quando non viene creato un nuovo IndexSearcher. Abbiamo bisogno di un modo per notificare al nostro codice che il processo di indicizzazione è terminato e quindi possiamo ripristinare il nostro oggetto IndexSearchContext singleton. Come potremmo integrare questa logica nel codice configurato da Sitecore?

Quando si ricostruisce l'indice manualmente richiede solo circa 5 secondi. Ovviamente questo elimina efficacemente l'indice e poi lo crea di nuovo, ma perché l'aggiornamento dell'articolo per articolo richiede così tanto tempo? Non c'è un modo migliore in cui il processo di aggiornamento può essere raggiunto senza andare voce per articolo e non influisce sul sito web pubblico?

mi sarei aspettato altri di essere colpiti da questo problema, quindi sono ansioso di sentire come le persone hanno affrontato il problema.

EDIT - informazioni aggiuntive da Sitecore forum

Il codice Sitecore.Search sembra di fare un uso pesante di creazione/smaltimento nuovi oggetti Lucene per una singola operazione. Non sembra eccessivamente scalabile per ambienti di grandi dimensioni, motivo per cui sono rimasto sorpreso quando ho visto il codice. Soprattutto se gli indici sono grandi e ci sono molti aggiornamenti di contenuti/pubblicati ogni giorno.

Guardando le classi tramite dotPeek non riesco a vedere come faremo a scavalcare IndexUpdateContext poiché è stato creato in un metodo non virtuale. Un DatabaseCrawler personalizzato potrebbe ottenere un accesso, ma solo all'oggetto contesto già creato.

Ho notato che possiamo definire la nostra implementazione Index nel web.config per ogni indice. Possiamo anche ri-implementare il crawler (abbiamo già il crawler avanzato sul posto dal modulo condiviso) e forse ottenere un certo controllo del processo di indicizzazione. Sarei riluttante a ritirare troppo del codice Sitecore nella nostra implementazione in quanto potrebbe influire sugli aggiornamenti futuri.

Ho una domanda però per quanto riguarda l'IndexingProvider.Nella seguente metodo:

private void UpdateItem(HistoryEntry entry, Database database) 
    { 
     int count = database.Indexes.Count; 
     if (count != 0 || this.OnUpdateItem != null) 
     { 
     Item obj = database.GetItem(entry.ItemId, entry.ItemLanguage, entry.ItemVersion); 
     if (obj != null) 
     { 
      if (this.OnUpdateItem != null) 
      this.OnUpdateItem((object) this, (EventArgs) new SitecoreEventArgs("index:updateitem", new object[2] 
      { 
       (object) database, 
       (object) obj 
      }, new EventResult())); 
      for (int index = 0; index < count; ++index) 
      database.Indexes[index].UpdateItem(obj); 
     } 
     } 
    } 

Esso genera l'evento di aggiornamento, che viene gestito dal DatabaseCrawler quanto allega all'evento IndexingProvider.OnUpdateItem; ma perché il metodo sopra chiama anche il metodo Sitecore.Data.Indexing.Index.UpdateItem? Ho pensato che lo spazio dei nomi fosse deprezzato nella versione 6.5, quindi sono sorpreso di vedere un collegamento tra il nuovo e il vecchio spazio dei nomi.

Quindi sembra che DatabaseCrawler gestisca l'aggiornamento, che elimina l'elemento e quindi lo aggiunge nuovamente all'indice; e quindi il vecchio Sitecore.Data.Indexing.Index tenta anche di aggiornarlo. Sicuramente c'è qualcosa di sbagliato qui? Non so però, per favore correggimi se sbaglio, è proprio come appare quando rintraccio il codice decompilato senza alcun debug.

+0

Questo mi sembra (roba e piuttosto pulito) avanzato hai intenzione di fare (e avete fatto finora). Forse dovresti provare a parlarne con Sitecore ... se hai dei miglioramenti, sono sicuro che amano sentirli :) – Holger

+1

Ciao Tim, potrei solo immaginare questo, quando l'indice è completamente ricostruito su ogni pubblicazione o se hai una grande quantità di utenti che fanno ricerche. Avete una grande quantità di visitatori o qualcosa di speciale istituito per la ricostruzione? Potresti provare e disabilitare l'aggiornamento dell'indice e poi fare lo stesso test? Potrebbe essere correlato alla pubblicazione in generale e non solo all'indicizzazione. –

+0

@Jens, grazie proveremo a disabilitare il processo dell'indice. Non mi sembra che stiamo facendo qualcosa di straordinario in termini di dimensioni del contenuto o quantità di visitatori. Il sito è relativamente piccolo. Ma abbiamo bisogno di sapere che le prestazioni aumenteranno progressivamente. Se l'indice è completamente ricostruito, funziona molto più rapidamente, circa 5 secondi per una ricostruzione completa.Aggiornare ciascun elemento uno per uno può richiedere molto più tempo di quanto si immagini. –

risposta

2

consiglierei due cose:

  1. Utilizzare il Advanced Database Crawler (v2 è l'ultima versione), che avvolge il Sitecore.Search namespace. Ciò semplifica l'utilizzo di Lucene.NET con Sitecore.

  2. Ricostruire gli indici completamente giornalmente. Questo deframmenta gli indici in quanto la frammentazione nel tempo può ridurre le prestazioni (che potrebbe essere il tuo problema qui).

+0

Ho provato ad utilizzare ADC, il suo impatto sulla soluzione. Più tardi, l'ho rimosso. –

1

Mi sono già imbattuto in problemi simili. Quando sono stato analizzato ciò che stava accadendo tutto il tempo è stato speso nell'aprire l'indice per ogni ricerca.

Il modo in cui abbiamo finito per risolverlo era bypassando le classi di indice di Sitecore e andando direttamente a Lucene. Lucene fornisce un metodo di "riapertura" che apre solo i file di segmento modificati, a differenza di tutti i file di segmento come Sitecore.

Quindi quello che abbiamo fatto è stata:

  1. Aprire un lettore di indice, se non abbiamo avuto già uno
  2. creare un riferimento a livello di applicazione ad esso, in modo da poter riutilizzare lo
  3. su ogni chiamata di ricerca "Riaprire" sul lettore indice di applicazione
  4. Ricerca

Date un'occhiata al Lucene.Net.Index.IndexReader.Reopen me ThOD Documentation

È possibile creare un lettore di indice da Sitecore.Search.Index.CreateReader()