Struttura di un indice full-text

Comprendere a fondo la struttura di un indice full-text è fondamentale per comprendere il funzionamento del motore di ricerca full-text. In questo argomento viene utilizzato come esempio l'estratto seguente della tabella Document in Adventure Works. In questo estratto vengono visualizzate solo due colonne, la colonna DocumentID e la colonna Title, e tre righe della tabella.

In questo esempio si suppone che nella colonna Title sia stato creato un indice full-text.

DocumentID

Title

1

Crank Arm and Tire Maintenance

2

Front Reflector Bracket and Reflector Assembly 3

3

Front Reflector Bracket Installation

Nella tabella seguente, Fragment 1, viene illustrato il contenuto dell'indice full-text creato nella colonna Title della tabella Document. Gli indici full-text contengono più informazioni rispetto a quelle riportate in questa tabella. La tabella è una rappresentazione logica di un indice full-text e ha solo scopo illustrativo. Per ottimizzare l'utilizzo del disco, le righe vengono archiviate in un formato compresso.

Si noti che i dati sono stati invertiti dai documenti originali. Questa inversione è dovuta al fatto che le parole chiave vengono mappate agli ID documento. Per questo motivo, un indice full-text viene spesso definito come un indice invertito.

Si noti inoltre che la parola chiave "and" è stata rimossa dall'indice full-text, trattandosi di una parola non significativa, e che la rimozione di tali parole da un indice full-text può contribuire a risparmiare spazio su disco, migliorando di conseguenza le prestazioni delle query. Per ulteriori informazioni sulle parole non significative, vedere Parole non significative ed elenchi di parole non significative.

Fragment 1

Parola chiave

ColId

DocId

Occurrence

Crank

1

1

1

Arm

1

1

2

Tire

1

1

4

Maintenance

1

1

5

Front

1

2

1

Front

1

3

1

Reflector

1

2

2

Reflector

1

2

5

Reflector

1

3

2

Bracket

1

2

3

Bracket

1

3

3

Assembly

1

2

6

3

1

2

7

Installation

1

3

4

La colonna Parola chiave contiene la rappresentazione di un singolo token estratto al momento dell'indicizzazione. I word breaker stabiliscono il modo in cui un token viene determinato.

La colonna ColId contiene un valore che corrisponde a una particolare colonna con indicizzazione full-text.

La colonna DocId contiene valori per un integer a otto byte mappato a un determinato valore chiave full-text in una tabella con indicizzazione full-text. Questo mapping è necessario se la chiave full-text non è un tipo di dati integer. In questi casi, i mapping tra i valori chiave full-text e i valori DocId vengono mantenuti in una tabella separata denominata DocId Mapping. Per eseguire una query per questi mapping utilizzare la stored procedure di sistema sp_fulltext_keymappings. Per soddisfare una condizione di ricerca, è necessario creare un join tra i valori DocId della tabella precedente e la tabella DocId Mapping per recuperare le righe dalla tabella di base su cui viene eseguita la query. Se il valore della chiave full-text della tabella di base è di tipo integer, il valore viene utilizzato direttamente come DocId e non è necessario alcun mapping. Pertanto, l'utilizzo di valori chiave full-text di tipo integer può contribuire all'ottimizzazione delle query full-text.

La colonna Occurrence contiene un valore di tipo integer. Per ogni valore DocId è presente un elenco di valori di occorrenza corrispondenti agli offset relativi di una particolare parola chiave all'interno di DocId. I valori di occorrenza sono utili per determinare le corrispondenze di frase o prossimità, ad esempio frasi con valori di occorrenza numericamente adiacenti. Sono inoltre utili per calcolare i punteggi di pertinenza, ad esempio il numero di occorrenze di una parola chiave in un DocId può essere utilizzato per l'assegnazione del punteggio.

Frammenti di indice full-text

L'indice full-text logico viene in genere suddiviso tra più tabelle interne. Ogni tabella interna viene definita un frammento di indice full-text. Alcuni di questi frammenti potrebbero contenere dati più recenti di altri. Ad esempio, se un utente aggiorna la riga seguente il cui DocId è 3 e per la tabella è impostato il rilevamento automatico delle modifiche, viene creato un nuovo frammento.

DocumentID

Title

3

Rear Reflector

Nell'esempio seguente, Fragment 2, il frammento contiene dati più recenti su DocId 3, rispetto a Fragment 1. Pertanto, quando viene eseguita una query per "Rear Reflector" i dati di Fragment 2 vengono utilizzati per DocId 3. Ogni frammento viene contrassegnato con un timestamp di creazione su cui è possibile eseguire query tramite la vista del catalogo sys.fulltext_index_fragments.

Fragment 2

Parola chiave

ColId

DocId

Occ

Rear

1

3

1

Reflector

1

3

2

Come si può vedere da Fragment 2, le query full-text devono essere eseguite internamente su ogni frammento e le voci più obsolete devono essere eliminate. Un numero eccessivo di frammenti di indice full-text nell'indice full-text può causare un calo sensibile delle prestazioni di esecuzione delle query. Per ridurre il numero di frammenti, riorganizzare il catalogo full-text tramite l'opzione REORGANIZE dell'istruzione ALTER FULLTEXT CATALOGTransact-SQL. Questa istruzione consente di eseguire un'unione nell'indice master, ovvero un'unione dei frammenti in un singolo frammento più grande e la rimozione di tutte le voci obsolete dall'indice full-text.

Dopo essere stato riorganizzato, l'indice di esempio dovrebbe contenere le righe seguenti:

Parola chiave

ColId

DocId

Occ

Crank

1

1

1

Arm

1

1

2

Tire

1

1

4

Maintenance

1

1

5

Front

1

2

1

Rear

1

3

1

Reflector

1

2

2

Reflector

1

2

5

Reflector

1

3

2

Bracket

1

2

3

Assembly

1

2

6

3

1

2

7