Programmer's Reference Guide

Erweitert

Beste Praxis

Feldnamen

Es gibt keine Begrenzungen für Feldnamen in Zend_Search_Lucene.

Trotzdem ist es eine gute Idee die 'id' und 'score' Namen nicht zu verwenden um Doppeldeutigkeiten in den Namen der QueryHit Eigenschaften zu verhindern.

Die Zend_Search_Lucene_Search_QueryHit id und score Eigenschaften referieren immer zum internen Lucene Dokumenten ID und Treffer- Anzahl. Wenn ein indiziertes Dokument das gleiche Feld gespeichert hat, muß die getDocument() Methode verwendet werden um darauf zuzugreifen:

<?php
$hits = $index->find($query);

foreach ($hits as $hit) {
    // Das 'title' Dokumentfeld erhalten
    $title = $hit->title;

    // Das 'contents' Dokumentfeld erhalten
    $contents = $hit->contents;


    // Die interne Lucene Dokument ID erhalten
    $id = $hit->id;

    // Die Anzahl der Abfragetreffer erhalten
    $score = $hit->score;


    // Das 'id' Dokumentfeld erhalten
    $docId = $hit->getDocument()->id;

    // Das 'score' Dokumentfeld erhalten
    $docId = $hit->getDocument()->score;

    // Ein anderer Weg um das 'title' Dokumentfeld zu erhalten
    $title = $hit->getDocument()->title;
}
            

Geschwindigkeit von Indezes

Die Geschwindigkeit von Indezes ist ein Kompromiss zwischen verwendeten Ressourcen, der Zeit für das Indizieren und die Qualität des Index.

Die Qualität des Index wird komplett eruiert durch die Anzahl an Indexsegmenten.

Jedes Indexsegment ist ein komplett unabhängiger Teil von Daten. Deshalb benötigt ein Index der mehr Segmente hat, auch mehr Speicher und mehr Zeit für das Suchen.

Index Optimierung ist ein Prozess der mehrere Segmente in ein neues zusammenfügt. Ein komplett optimierter Index enthält nur ein Segment.

Komplette Index Optimierung kann mit der 'optimize()' Methode durchgeführt werden:

<?php
$index = Zend_Search_Lucene::open($indexPath);

$index->optimize();
            

Index Optimierung arbeitet mit Daten Streams und benötigt nicht viel Speicher, aber Prozessor Ressourcen und Zeit.

Lucene Index Segmente sind nicht aktualisierbar durch Ihre Natur (Aktuslisierung erfordert das die Segment Datei komplett neu geschrieben wird). Deshalb erzeugt das Hinzufügen neuer Dokumente zu einem Index auch immer ein neues Segment. Das verkleinert die Qualität des Indexes.

Der automatische Optimierungsprozess des Index wird nach jeder Erstellung eines Segments durchgeführt und besteht darin das verschiedene Segmente zusammengeführt werden.

Es gibt drei Optionen um das Verhalten der automatischen Optimierung zu beeinflussen (siehe das Kapitel Index Optimierung):

  • MaxBufferedDocs ist die Anzahl an Dokumenten die im Speicher gepuffert werden bevor ein neues Segent erstellt und auf die Festplatte geschrieben wird.

  • MaxMergeDocs ist die maximale Anzahl an Dokumenten die durch den automatischen Optimierungsprozess in ein neues Segment zusamengeführt werden.

  • MergeFactor ermittelt wie oft die automatische Optimierung durchgeführt wird.

Hinweis: Alle diese Optionen sind Eigenschaften des Zend_Search_Lucene Objektes, aber keine Eigenschaften des Index. Deshalb beeinflussen Sie nur das Verhalten des aktuellen Zend_Search_Lucene Objektes und können für verschiedene Skripte unterschiedlich sein.

MaxBufferedDocs ist es egal ob nur ein Dokument pro Skriptausführung indiziert wird. Im Gegensatz dazu ist das sehr wichtig für die Batchindizierung. Größere Werte erhöhen die Geschwindigkeit des Indizierens, benötigen aber auch mehr Speicher.

Es gibt keinen Weg um den besten Wert für den MaxBufferedDocs Parameter zu berechnen weil es von der Größe des Dokuments abhängt, dem verwendeten Analysierer und dem erlaubten Speicher.

Ein guter Weg um den richtigen Wert herauszufinden, ist die Durchführung von verschiedenen Tests mit den größten Dokumenten von denen erwartet wird das Sie indiziert werden. [1] memory_get_usage()memory_get_peak_usage() Es ist eine gute Idee nicht mehr als die Hälfte des erlaubten Speichers zu verwenden.

MaxMergeDocs limitiert die Größe des Segments (in Abschnitten von Dokumenten). Es begrenzt also die Zeit für die automatische Optimierung. Das garantiert das die addDocument() Methode nicht länger als eine bestimmte Zeit ausgeführt wird. Das ist wichtig für interaktive Anwendungen.

Das Verkleinern des MaxMergeDocs Parameters kann auch die Geschwindigkeit des Batchinzieierens beeinflussen. Automatische Optimierung des Index ist ein iterativer Prozess und wird Schritt für Schritt durchgeführt. Kleine Segmente werden in größere zusammengeführt, und irgendwann werden Sie in sogar noch größere zusammengeführt und so weiter. Komplette Optimierung des Index ist viel effektiver.

Auf der anderen Seite, verkleinern kleiner Segmente die Qualität des Indezes und können zu viele Segmente erzeugen. Das kann zu einem "Too many open files" Fehler führen, ausgelöst durch die Beschränkungen des Betriebsystems. [2]

Deshalb sollte die Optimierung des Indezes im Hintergrund für den Interaktiven Indexmodus durchgeführt werden und MaxMergeDocs sollte nichz zu klein sein für die Batchindizierung.

MergeFactor beeinflußt die Frequenz der automatischen Optimierung. Kleinere Werte erhöhen die Qualität des nicht optimierten Index. Größere Werte erhöhen die Geschwindigkeit des Indizierens, erhöht aber auch die Anzahl an Segmenten. Das kann auch wieder zu einem Fall von "Too many open files" Fehler führen.

MergeFactor gruppiert Indexsegmente anhand Ihrer Größe:

  1. Nicht größer als MaxBufferedDocs.

  2. Größer als MaxBufferedDocs, aber nicht größer als MaxBufferedDocs*MergeFactor.

  3. Größer als MaxBufferedDocs*MergeFactor, aber nicht größer als MaxBufferedDocs*MergeFactor*MergeFactor.

  4. ...

Zend_Search_Lucene prüft bei jedem Aufruf von addDocument() ob das Zusammenführen irgendwelcher Segmentgruppen dazu führt das neu erstellte Segmente in die nächste Gruppe verschoben werden. Wenn ja, wird das Zusammenführen durchgeführt.

Also kann ein Index mit N Gruppen MaxBufferedDocs + (N-1)*MergeFactor Segmente und zumindest MaxBufferedDocs*MergeFactor(N-1) Dokumente enthalten.

Das gibt eine gute Näherung für die Anzahl an Segmenten im Index:

NumberOfSegments <= MaxBufferedDocs + MergeFactor*log MergeFactor (NumberOfDocuments/MaxBufferedDocs)

MaxBufferedDocs wird durch den erlaubten Speicher eruiert. Das bietet die Möglichkeit einen erwünschten Faktor für das Zusammenführen auszuwählen um eine erwünschte Anzahl an Segmenten zu erhalten.

Das tunen des MergeFactor Parameters ist effektiver für die Geschwindigkeit der Batchindizierung als MaxMergeDocs. Aber es ist auch grober. Deshalb sollte die obige Annäherung für das tuten von MergeFactor verwendet werden und anschließend mit MaxMergeDocs gespielt werden um die beste Geschwindigkeit für die Batchindizierung zu erhalten.

Den Index herunterfahren

Ein Zend_Search_Lucene Objekt führt einiges an Arbeit durch während des Herunterfahrens wenn irgendwelche Dokumente dem Index hinzugefügt wurden.

Es ist Beschäftigt mit dem Buffern von hinzugefügten Dokumenten bevor ein neues Segment erstellt wird.

Es kann auch einen automatischen Optimierungsprozess ausführen.

Das Indexobjekt wird automatisch Heruntergefahren wenn es selbst, und alle zurückgegebenen QueryHit Objekte, ausserhalb des Sichtbereichs sind.

Wenn das Indexobjekt in einer globalen Variable gespeichert wird, dann wird es nur am Ende der Skriptausführung zerstört [3] .

Die Behandlung von PHP Ausnahmen ist aktuell auch ein Herunterfahren.

Das beeinflußt den normalen Shutdown Prozess des Index nicht, kann aber verhindern das korrekte Fehlerdisgnostik durchgeführt werden kann wenn ein Fehler stattfindet.

Es gibt zwei Wege welche helfen das Problem zu verhindern.

Der erste ist, das das Herausgehen aus dem Sichtbereich erzwungen wird:

<?php
$index = Zend_Search_Lucene::open($indexPath);

...

unset($index);
            

Und der zweite ist, das eine commit Operation vor dem Ende der Ausführung des Skripts stattfindet:

<?php
$index = Zend_Search_Lucene::open($indexPath);

$index->commit();
            
Diese Möglichkeit wird auch im Kapitel "Fortgeschrittene Verwendung von Indezes als statische Eigenschaften" der Dokumentation beschrieben.

Dokumente anhand der eindeutigen Id erhalten

Es ist eine übliche Praxis das eindeutige Dokument IDs in dem Index gespeichert werden. Zum Beispiel URL, Pfad, Datenbank ID oder einige andere.

Zend_Search_Lucene bietet die termDocs() Methode damit Dokumente empfangen werden können die spezielle Terme enthalten.

Das ist effektiver als die find() Methode:

<?php
// Dokumente mit find() erhalten indem ein Abfragestring verwendet wird
$query = $idFieldName . ':' . $docId;
$hits  = $index->find($query);
foreach ($hits as $hit) {
    $title    = $hit->title;
    $contents = $hit->contents;
    ...
}
...

// Dokumente mit der find() Methode erhalten indem die Anfrage API verwendet wird
$term = new Zend_Search_Lucene_Index_Term($docId, idFieldName);
$query = new Zend_Search_Lucene_Search_Query_Term($term);
$hits  = $index->find($query);
foreach ($hits as $hit) {
    $title    = $hit->title;
    $contents = $hit->contents;
    ...
}

...

// Dokumente mit der termDocs() Methode erhalten
$term = new Zend_Search_Lucene_Index_Term($docId, idFieldName);
$docIds  = $index->termDocs($term);
foreach ($docIds as $id) {
    $doc = $index->getDocument($id);
    $title    = $doc->title;
    $contents = $doc->contents;
    ...
}
            

Speicherverwendung

Zend_Search_Lucene ist ein Modul das sehr viel Speicher benötigt.

Es verwendet Speicher um Informationen zu cachen und das Suchen und Indizieren schneller zu machen.

Es verhält sich unterschiedlich für unterschiedliche Modi.

Der Verzeichnisindex der Terme wird während der Suche geladen. Das ist aktuelle jeder 128 te Term des kompletten Verzeichnisses. [4]

Der Speicherverbrauch wird erhöht wenn man eine große Anzahl an eindeutigen Termen hat. Das kann passieren wen man ungeteilte Phrasen als Feld Werte verwendet, oder ein großes Volumen von nicht-text Informationen hat.

Ein nicht optimierter Index besteht aus verschiedenen Segmenten. Er erhöht auch den Speicherverbrauch. Segmente sind voneinander unabhängig, sodas jedes Segment sein eigenes Verzeichnis an Termen enthält und den Verzeichnisindex der Terme. Wenn der Index aus N Segmenten besteht kann der Speicherverbrauch im schlimmsten Fall N mal so groß sein. Eine Optimierung des Index kann durchgeführt werden um alle Segmente in eines zusammenzuführen.

Indizierung verwendet den gleichen Speicher wie das Suchen und zusätzlich Speicher für das puffern von Dokumenten. Die Größe des Speichers der hierfür verwendet wird kann mit dem MaxBufferedDocs Parameter verwaltet werden.

Index Optimierung (komplett oder teilweise) verwendet Streams wie beim Bearbeiten von Daten und benötigt nicht viel Speicher.

Verschlüsselung

Zend_Search_Lucene arbeitet intern mit UTF-8 Strings. Das bedeutet also das alle von Zend_Search_Lucene zurückgegebenen Strings UTF-8 verschlüsselt sind.

Man sollte sich keine Gedanken über Verschlüsselung machen solange man mit reinen ASCII Daten arbeitet, aber in allen anderen Fällen sollte man Vorsichtig sein.

Eine falsche Verschlüsselung kann Fehlernotizen bei der Konvertierung der Verschlüsselung oder den Verlust von Daten verursachen.

Zend_Search_Lucene bietet einen weiten Bereich von Möglichkeiten um die aktuelle Verschlüsselung von indizierten Dokumenten zu spezifizieren und Abfragen zu parsen.

Verschlüsselung kann explizit als optionaler Parameter bei den Felderstellung Methoden spezifiziert werden:

<?php
$doc = new Zend_Search_Lucene_Document();
$doc->addField(Zend_Search_Lucene_Field::Text('title', $title, 'iso-8859-1'));
$doc->addField(Zend_Search_Lucene_Field::UnStored('contents', $contents, 'utf-8'));
            
Das ist der beste Weg um Problemen bei der Spezifikation von Verschlüsselung vorzubeugen.

Wenn der optionale Parameter der Verschlüsselung unterdrückt wird, wird das aktuelle Gebietsschema verwendet zusätzlich zur Information der Sprache.

<?php
setlocale(LC_ALL, 'fr_FR');
...

setlocale(LC_ALL, 'de_DE.iso-8859-1');
...

setlocale(LC_ALL, 'ru_RU.UTF-8');
...
            

Der selbe Weg wird verwendet um die Verschlüsselung beim Abfragestring zu spezifizieren.

Wenn die Verschlüsselung nicht auf einen speziellen Weg definiert wird, wird das aktuelle Gebietsschema verwendet.

Verschlüsselung kann als optionaler Parameter angegeben werden, wenn die Abfrage explizit vor der Suche geparsed wird:

<?php
$query = Zend_Search_Lucene_Search_QueryParser::parse($queryStr, 'iso-8859-5');
$hits = $index->find($query);
...
            

Die Standardverschlüsselung kann auch mit der setDefaultEncoding() Methode spezifiziert werden:

<?php
Zend_Search_Lucene_Search_QueryParser::setDefaultEncoding('iso-8859-1');
$hits = $index->find($queryStr);
...
            
Ein leerer String bedeutet das 'aktuelle Gebietsschema'.

Sobald die richtige Verschlüsselung spezifiziert wurde, kann Sie korrekt vom Analysator ausgeführt werden. Das aktuelle Verhalten hängt vom verwendeten Analysator ab. Siehe das Kapitel Zeichensatz der Dokumentation für Details.

Index Wartung

Es sollte klar sein, das Zend_Search_Lucene, genauso wie jede andere Lucene Implementation, keine "Datenbank" ist.

Es sollte auf einigen Arten von Datenspeichern nicht verwendet werden. Es bietet keine teilweisen Backup/Wiederherstellungs Funktionen, Journal, Logging, Transactions und viele andere Dinge die von Datenbank Management Systemen angeboten werden.

Trotzdem versucht Zend_Search_Lucene den Index jederzeit in einem gültigen Status zu halten.

Index Backup/Wiederherstellung sollte off-line durchgeführt werden durch komplettes Kopieren des Index Verzeichnisses.

Wenn der Index durch irgendeinen Grund beschädigt wird, sollte er komplett wiederhergestellt oder neu gebaut werden.

Es ist also eine gute Idee von großen Indezes ein Backup zu machen und irgendwo ein Änderungslog zu speichern um manuelle Wiederherstellung + Roll-Forward Operationen durchzuführen wenn das notwendig ist. Es ist essentiell die Wiederherstellungszeit des Index zu reduzieren.

[1] und können verwendet werden um die Verwendung des Speichers zu kontrollieren.
[2] Zend_Search_Lucene hält jedes Segment offen um die Geschwindigkeit des Suchens zu erhöhen.
[3] Das kann auch vorkommen das, wenn Index oder QueryHit Objekte im komplexen Datenstrukturen referenziert werden. Z.B. zerstört PHP Objekte mit zyklischen Referenzen nur am Ende der Skriptausführung.
[4] Das Lucene Dateiformat erlaubt es diese Zahl zu ändern, aber Zend_Search_Lucene bietet keine Möglichkeit das über seine API durchzuführen. Trotzdem gibt es die Möglichkeit diesen Wert zu ändern wenn er mit einer anderen Lucene Implementation vorbereitet wird.

Erweitert
blog comments powered by Disqus

Select a Version

Languages Available

Components

Search the Manual