{"id":34,"date":"2007-05-23T16:41:06","date_gmt":"2007-05-23T14:41:06","guid":{"rendered":"http:\/\/robert.kolatzek.org\/wblog\/?p=34"},"modified":"2007-05-23T16:41:06","modified_gmt":"2007-05-23T14:41:06","slug":"sphinx-search-engine-installation-und-betrieb-eine-einleitung","status":"publish","type":"post","link":"https:\/\/blog.kolatzek.org\/wblog\/34\/sphinx-search-engine-installation-und-betrieb-eine-einleitung","title":{"rendered":"Sphinx search engine: Installation und Betrieb &#8211; eine Einleitung"},"content":{"rendered":"<p>http:\/\/www.sphinxsearch.com Sphinx Search Engine, die &#8211; wie sie sich selber nennt &#8211; &#8222;Free open-source SQL full-text search engine&#8220; ist ein gutes tool, um die Volltextsuche auf dem eigenen Server zu beschleunigen. Der Ansatz ist gut, die Ergebnisse noch besser, aber die Installation ein langer Leidensweg&#8230; Da dies \u00f6fters bei Open Source Projekten der Fall ist, muss man wohl oder \u00fcber nach Anleitungen Ausschau halten, um genau das nicht selber durchmachen zu m\u00fcssen.<br \/>\nEine solche Anleitung soll dieser Artikel sein. <\/p>\n<p><!--more--><\/p>\n<p>In Max&#8216; Tagebuch fand ich eine gute Hilfe, um das Grundproblem zu knacken: Wie komme ich an die binaries (fertig kompillierte Programme)&#8230;<\/p>\n<p>Leider w\u00e4hrte meine Freude nur kurz: die Beschreibung stimmt mittlerweile nicht mehr ganz. Und eine Erkl\u00e4rung, wie man die Konfig-Datei einrichtet war sowieso nicht dabei! Deshalb fangen wir mal bei 0 (NULL) an!<\/p>\n<p>Von der Download-Seite von MySQL besorgen wir aus der Abteilung<br \/>\n&#8222;Source Downloads&#8220; &#8222;Compressed GNU TAR archive (tar.gz)&#8220;<br \/>\nz.B. per:<\/p>\n<p><code>wget ftp:\/\/sunsite.informatik.rwth-achen.de\/pub\/mirror\/www.mysql.com\/Downloads\/MySQL-5.0\/mysql-5.0.41.tar.gz <\/code><br \/>\nund nat\u00fcrlich sphinx:<br \/>\n<code>wget http:\/\/www.sphinxsearch.com\/downloads\/sphinx-0.9.7.tar.gz <\/code><\/p>\n<p>Nat\u00fcrlich k\u00f6nnen die Versionen variieren und die Patches von sphinx k\u00f6nnen f\u00fcr die neuste Version von MySQL nicht anwendbar sein &#8211; hier hilft nur die Festlegung auf die hier beschriebene Versionen &#8211; die funktionieren zumindest&#8230;<\/p>\n<p>Mit <\/p>\n<p><code> tar xzf sphinx-0.9.7.tar.gz &amp;&amp; tar xzf mysql-5.0.41.tar.gz<\/code><br \/>\nentpacken wir die beiden und schreiten zur Tat:<\/p>\n<p>Wir installieren notwendige development Packete:<\/p>\n<p><code>apt-get install libmysqlclient15-dev libtool debhelper<br \/>\nlibncurses5-dev libwrap0-dev zlib1g-dev libreadline-dev<br \/>\nchrpath automake1.8 automake1.9 doxygen dpatch procps<br \/>\nfile perl psmisc po-debconf tetex-bin tetex-base tetex-extra gs gawk bison <\/code> <\/p>\n<p>bei Debian und seinen Kindern<br \/>\nbzw.<\/p>\n<p>&#8222;yum install mysqlclient14-devel mysql-devel doxygen gcc automake readline-devel byacc libtool bison&#8220;<\/p>\n<p>bei den roten H\u00fcten und \u00c4hnlichen&#8230;<\/p>\n<p>Jetzt m\u00fcssten wir alles n\u00f6tige f\u00fcr eine erfolgreiche Kompilation haben. Wenn nicht, kann nur die Suche nach fehlenden libraries in \/usr\/include\/ helfen&#8230; Vorsicht ist bei einigen \u00e4lteren Distributionen geboten: g++ und gcc wird in Version 4 (bzw 4.1) verlangt. Sollte es auch dann nicht funktionieren und ein &#8222;&#8211;preserve-dup-deps: command not found&#8220; erscheint, muss man den Pfad zu libtool setzten (mysql hat libtool im eigenen Quellen-Verzeichnis drin, es wird bei .\/configfure-Aufruf erstellt), es reicht in configure im MySQL-Quellen-Verzeichnis die Zeile &#8222;LIBTOOL=&#8220; &#8211;preserve-dup-deps&#8220; &#8220; mit &#8222;LIBTOOL=&#8220;\/pfad\/zu\/mysql-quelle-5.0.xx\/libtool &#8211;preserve-dup-deps&#8220; &#8220; zu ersetzten oder noch einfacher: &#8222;LIBTOOL=&#8220;\/pfad\/zu\/mysql-quelle-5.0.xxx\/libtool&#8220; in der Shell abzusetzten.)<\/p>\n<p>Jetzt kompilieren wir Sphinx<\/p>\n<p><code>cd ..\/sphinx-0.9.7<\/code> (da w\u00e4ren wir im Sphinx Quellen-Verzeichnis)<\/p>\n<p><code>.\/configure --prefix=\/usr --with-mysql<\/code> wird Alles f\u00fcr die Nutzung von sphinx (mit MySQL-Anbindung) vorbereiten. Die Binaries landen nach der Installation in \/usr\/bin\/ \/usr\/lib statt in \/usr\/local\/bin und \/usr\/local\/lib.<\/p>\n<p>Etwas sinnlos landet die Beispiel-Konfigurationsdatei sphinx.conf.dist in \/usr\/etc. Nicht weiter schlimm! Wir verschieben sie einfach:<br \/>\n&#8222;mv \/usr\/etc\/sphinx.conf.dist \/etc&#8220;<\/p>\n<p>Jetzt noch ein startscript f\u00fcr den searchd (search daemon). Er bedient den start-, restart- und stop-Aufruf in redhat und debian Systemen (\u00fcberarbeitete Version von Max&#8216; Tagebuch Blog):<\/p>\n<p>\/etc\/init.d\/searchd<br \/>\n<code><br \/>\n#! \/bin\/sh<br \/>\n### BEGIN INIT INFO<br \/>\n# Provides:          searchd<br \/>\n# Required-Start:    $local_fs $remote_fs<br \/>\n# Required-Stop:     $local_fs $remote_fs<br \/>\n# Default-Start:     2 3 4 5<br \/>\n# Default-Stop:      S 0 1 6<br \/>\n# Short-Description: Example initscript<br \/>\n# Description:       This file should be used to construct scripts to be<br \/>\n#                    placed in \/etc\/init.d.<br \/>\n### END INIT INFO<\/p>\n<p>#<br \/>\n# Do NOT \"set -e\"<\/p>\n<p># PATH should only include \/usr\/* if it runs after the mountnfs.sh script<br \/>\nPATH=\/usr\/sbin:\/usr\/bin:\/sbin:\/bin<br \/>\nDESC=\"Sphinx Index Query Daemon\"<br \/>\nNAME=searchd<br \/>\nDAEMON=\/usr\/bin\/$NAME<br \/>\nINDEXER=\/usr\/bin\/indexer<br \/>\nDAEMON_ARGS=\"--config \/etc\/sphinx.conf\"<br \/>\nPIDFILE=\/var\/run\/searchd.pid<br \/>\nSCRIPTNAME=\/etc\/init.d\/$NAME<br \/>\ninitdir=\/etc\/init.d<br \/>\nsystem=unknown<\/p>\n<p>if [ -f \/etc\/debian_version ]; then<br \/>\n    system=debian<br \/>\nelif [ -f \/etc\/redhat-release ]; then<br \/>\n    system=redhat<br \/>\nelse<br \/>\n    echo \"$0: Unknown system, please port\" 1&gt;&amp;2<br \/>\n    exit 1<br \/>\nfi<\/p>\n<p>if [ $system = redhat ]; then<br \/>\n    . $initdir\/functions<br \/>\nfi<\/p>\n<p>if [ $system = suse ]; then<br \/>\n    . \/etc\/rc.status<br \/>\nfi<\/p>\n<p>[ -x \"$DAEMON\" ] || exit 0<\/p>\n<p>[ -r \/etc\/default\/$NAME ] &amp;&amp; . \/etc\/default\/$NAME<\/p>\n<p>[ -f \/etc\/default\/rcS ] &amp;&amp; . \/etc\/default\/rcS<\/p>\n<p># Define LSB log_* functions.<br \/>\n# Depend on lsb-base (&gt;= 3.0-6) to ensure that this file is present.<br \/>\n. \/lib\/lsb\/init-functions<\/p>\n<p>#<br \/>\n# Function that starts the daemon\/service<br \/>\n#<br \/>\ndo_start()<br \/>\n{<br \/>\n\tif [ $system = debian ]; then<br \/>\n\t# Return<br \/>\n\t#   0 if daemon has been started<br \/>\n\t#   1 if daemon was already running<br \/>\n\t#   2 if daemon could not be started<br \/>\n\tstart-stop-daemon --start --quiet --pidfile $PIDFILE<br \/>\n\t\t--exec $DAEMON --test &gt; \/dev\/null<br \/>\n\t\t|| return 1<br \/>\n\t#Run Indexer before rest<br \/>\n\t$INDEXER $DAEMON_ARGS --all<br \/>\n\t#Start daemon<br \/>\n\tstart-stop-daemon --start --quiet --pidfile $PIDFILE<br \/>\n\t\t--exec $DAEMON -- $DAEMON_ARGS<br \/>\n\t\t|| return 2<br \/>\n\t# Add code here, if necessary, that waits for the process to be ready<br \/>\n\t# to handle requests from services started subsequently which depend<br \/>\n\t# on this one.  As a last resort, sleep for some time.<br \/>\n\tfi<br \/>\n\tif [ $system = redhat ]; then<br \/>\n\techo -n \"Starting searchd\"<br \/>\n\tdaemon $DAEMON $DAEMON_ARGS<br \/>\n\tfi<br \/>\n}<\/p>\n<p>#<br \/>\n# Function that stops the daemon\/service<br \/>\n#<br \/>\ndo_stop()<br \/>\n{<br \/>\n\tif [ $system = debian ]; then<br \/>\n\t# Return<br \/>\n\t#   0 if daemon has been stopped<br \/>\n\t#   1 if daemon was already stopped<br \/>\n\t#   2 if daemon could not be stopped<br \/>\n\t#   other if a failure occurred<br \/>\n\tstart-stop-daemon --stop --quiet --retry=TERM\/30\/KILL\/5<br \/>\n\t--pidfile $PIDFILE --name $NAME<br \/>\n\tRETVAL=\"$?\"<br \/>\n\t[ \"$RETVAL\" = 2 ] &amp;&amp; return 2<br \/>\n\t# Wait for children to finish too if this is a daemon that forks<br \/>\n\t# and if the daemon is only ever run from this initscript.<br \/>\n\t# If the above conditions are not satisfied then add some other code<br \/>\n\t# that waits for the process to drop all resources that could be<br \/>\n\t# needed by services started subsequently.  A last resort is to<br \/>\n\t# sleep for some time.<br \/>\n\tstart-stop-daemon --stop --quiet --oknodo --retry=0\/30\/KILL\/5<br \/>\n\t--exec $DAEMON<br \/>\n\t[ \"$?\" = 2 ] &amp;&amp; return 2<br \/>\n\t# Many daemons don't delete their pidfiles when they exit.<br \/>\n\trm -f $PIDFILE<br \/>\n\treturn \"$RETVAL\"<br \/>\n\tfi<br \/>\n        if [ $system = redhat ]; then<br \/>\n        echo -n \"Stopping searchd\"<br \/>\n        #daemon $DAEMON $DAEMON_ARGS<br \/>\n\t#PID=<br \/>\n\t#PID=$(cat $PIDFILE)<br \/>\n\t#kill $PID<br \/>\n\tkillproc $NAME<br \/>\n\techo<br \/>\n\trm -f $PIDFILE<br \/>\n\treturn $RETVAL<br \/>\n        fi<br \/>\n}<\/p>\n<p>case \"$1\" in<br \/>\n  start)<br \/>\n\tdo_start<br \/>\n\t;;<br \/>\n  stop)<br \/>\n\tdo_stop<br \/>\n\t;;<br \/>\n  restart|force-reload)<\/p>\n<p>\tif [ $system = debian ]; then<br \/>\n\t\tdo_stop<br \/>\n\t\tdo_start<br \/>\n\tfi<\/p>\n<p>\tif [ $system = debian ]; then<br \/>\n\tlog_daemon_msg \"Restarting $DESC\" \"$NAME\"<br \/>\n\tdo_stop<br \/>\n\t\tcase \"$?\" in<br \/>\n\t\t0|1)<br \/>\n\t\t\tdo_start<br \/>\n\t\t\tcase \"$?\" in<br \/>\n\t\t\t\t0) log_end_msg 0 ;;<br \/>\n\t\t\t\t1) log_end_msg 1 ;; # Old process is still running<br \/>\n\t\t\tesac<br \/>\n\t\t\t;;<br \/>\n\t\t*)<br \/>\n\t  \t\t# Failed to stop<br \/>\n\t\t\tlog_end_msg 1<br \/>\n\t\t\t;;<br \/>\n\t\tesac<br \/>\n\tfi<br \/>\n\t;;<br \/>\n  *)<br \/>\n\techo \"Usage: $SCRIPTNAME {start|stop|restart|force-reload}\" &gt;&amp;2<br \/>\n\texit 3<br \/>\n\t;;<br \/>\nesac<\/p>\n<p>:<br \/>\n<\/code><\/p>\n<p>Konfiguration von Sphinx<\/p>\n<p>Wir editieren: \/etc\/sphinx.conf.dist und speichern als \/etc\/sphinx.conf !!!<\/p>\n<p>\/etc\/sphinx.conf<br \/>\n<code><br \/>\n# die Datenquelle<br \/>\nsource source_CONTENT<br \/>\n{<br \/>\n# Typ der Datenquelle: 'mysql', 'pgsql' oder 'xmlpipe'. Wir nehmen mysql<br \/>\ntype = mysql<\/p>\n<p># HTML-Tags entfernen? Ja<br \/>\nstrip_html = 1<\/p>\n<p># Welche HTML-Attribute beim entfernen von Tags indexieren?<br \/>\n# ALT ,TITLE bei IMG und TITLE bei A, kann aber auch leer bleiben<br \/>\nindex_html_attrs = img=alt,title; a=title;<\/p>\n<p># Einstellungen f\u00fcr die Datenbank-Verbindung<br \/>\nsql_host = localhost<br \/>\nsql_user = root<br \/>\nsql_pass =<br \/>\nsql_db = myDB<br \/>\nsql_port = 3306 # optional, default is 3306<\/p>\n<p># Die Tabelle, die wir lesen wollen hei\u00dft CONTENT und enth\u00e4lt als BEISPIEL Inhalt eines<br \/>\n# CMS-Systems mit ID, Titel, Inhalt, Datum und Kategorie<br \/>\n# Wenn unsere zu indexierende Datenquelle sehr gro\u00df ist (&gt;1000), empfielt es sich,<br \/>\n# die Daten sequenziell zu lesen. Dazu legt man in der angegebenen DB eine Tabelle namens<br \/>\n# counters mit:<br \/>\n# CREATE TABLE `counters` (<br \/>\n# `id` int(11) NOT NULL,<br \/>\n# `val` int(11) NOT NULL,<br \/>\n# PRIMARY KEY (`id`)<br \/>\n# );<br \/>\n# Es legt die Start-ID und End-ID der zu lesenden Datens\u00e4tze (dabei wird einfach aus der<br \/>\n# Tabelle CONTENT die kleinste und die h\u00f6chste ID kopiert)<br \/>\n# Brauchst Du kein sequenzielles Lesen gehe weiter zu \" sql_query\"<br \/>\nsql_query_pre = REPLACE INTO counters SELECT 1, MAX(ID) FROM CONTENT<\/p>\n<p># main document fetch query<br \/>\n#<br \/>\n# die ID muss &gt;0, max 32 Bit und eindeutig (unique) sein<br \/>\n#<br \/>\n# (man kann zus\u00e4tzlich sog. Attribute anlegen, die gleichen Anforderungen bis auf unique<br \/>\n# unterliegen dazu sp\u00e4ter)<br \/>\n#<br \/>\n# Jetzt wird die L\u00e4nge einer Sequenz festgelegt: 1 Schritt = 1000 S\u00e4tze<br \/>\nsql_query_range = SELECT MIN(ID),MAX(ID) FROM CONTENT_DE<br \/>\nsql_range_step = 1000<\/p>\n<p># Jetzt lesen wir die zu indexierenden Datens\u00e4tze<br \/>\nsql_query =<br \/>\nSELECT<br \/>\nID<br \/>\nAUTOR,<br \/>\nTITLE,<br \/>\nARTICLE,<br \/>\nUNIX_TIMESTAMP(LAST_UPDATE) as LAST_UPDATE,<br \/>\nCATEGORY<br \/>\nFROM CONTENT<br \/>\nWHERE ID &gt;=$start AND ID  siehe unten \"docinfo\")<br \/>\n# Jetzt kommt die SQL-Anfrage, die zum Lesen einzelner Artikel dient.<br \/>\n# Dieser muss anhand von ID (siehe oben) gefunden werden k\u00f6nnen!<br \/>\nsql_query_info = SELECT * FROM CONTENT WHERE ID=$id<br \/>\n}<\/p>\n<p># Datenquelle haben wir, jetzt kommt die Definition des Indexes<br \/>\nindex index_CONTENT<br \/>\n{<br \/>\n# Aus welcher Quelle? Aus source_CONTENT (oben definiert)<br \/>\nsource = source_CONTENT<\/p>\n<p># tWohin mit den Dateien? Nach \/var\/lib\/sphinx\/INDEXNAME (Verzeichnis muss existieren!)<br \/>\npath = \/var\/lib\/sphinx\/index_CONTENT<\/p>\n<p># docinfo<br \/>\n# Drei M\u00f6glichkeiten: are \"none\", \"inline\" and \"extern\"<br \/>\n#<br \/>\n# \"none\" keine Informationen zum Artikel werden gespeichert<br \/>\n#<br \/>\n# \"inline\" Infos landen in doclist Datei (nur \u00fcber 50 Mil. Atikel sinnvoll)<br \/>\n#<br \/>\n# \"extern\" Infos landen in getrennter Datei<br \/>\n#<br \/>\n# Wohin mit DocInfos? \"extern\", weil unter 50 000 000 Artikel!<br \/>\ndocinfo = extern<\/p>\n<p># Morphologie: \"none\", \"stem_en\", \"stem_ru\", \"stem_enru\", \"soundex\"<br \/>\n# (\u00c4hnlichkeit anhand von Endungen: leider nur englisch und russisch)<br \/>\n# Beis soundex wird die Aussprache beachtet: google und googl sind gleich<br \/>\n# none -&gt; Keine \u00c4hnlichkeiten suchen<br \/>\n# F\u00fcr Wissenschaftler emphele ich Artikel \u00fcber Indexierung von Prof. Zimmermann<br \/>\nmorphology = none<\/p>\n<p># Pfad zur Stoppwort-Datei (datei mit W\u00f6rtern,<br \/>\n# die nicht indexiert werden sollen wie: \"und\", \"der\", \"die\", \"das\", \"ein\" )<br \/>\n#<br \/>\nstopwords = \/var\/lib\/sphinx\/stopwords.txt<\/p>\n<p># L\u00e4nge des k\u00fcrzesten Wortes? 2 Buchstaben (Wegen m\u00f6glicher Abk\u00fcrzungen \"AU\", \"T\u00dcV\")<br \/>\nmin_word_len = 2<\/p>\n<p># charset encoding ? Bei uns Latin1 also Single Byte -&gt; SBCS<br \/>\ncharset_type = sbcs<\/p>\n<p># 'sbcs' default value is<br \/>\n# charset_table = 0..9, A..Z-&gt;a..z, _, a..z, U+A8-&gt;U+B8, U+B8, U+C0..U+DF-&gt;U+E0..U+FF, U+E0..U+FF<br \/>\n#<br \/>\n# 'utf-8' default value is<br \/>\n# charset_table = 0..9, A..Z-&gt;a..z, _, a..z, U+410..U+42F-&gt;U+430..U+44F, U+430..U+44F<\/p>\n<p># Wie lang sind die zu indexierenden Prefixe? Bei und 0 -&gt; gar nicht indexieren<br \/>\nmin_prefix_len = 0<\/p>\n<p># L\u00e4nge der Infixe? (1 f\u00fcr deutsche Komposita mir \"s\" als Verbindung)<br \/>\nmin_infix_len = 1<br \/>\n}<\/p>\n<p># Verteilte Indexierung (auf mehreren Maschinen) - brauchen wir nicht<br \/>\n#index dist1<br \/>\n# {<br \/>\n# type = distributed<br \/>\n# lokal haben wir index-CONTENT<br \/>\n# local = index_CONTENT<br \/>\n# Auf anderen Maschinen<br \/>\n# Syntax: 'hostname:port:index1,[index2[,...]]<br \/>\n# BEISPIEL:<br \/>\n# agent = localhost:3313:index_CONTENT<br \/>\n# agent_connect_timeout = 1000<br \/>\n# agent_query_timeout = 3000<br \/>\n# }<\/p>\n<p>#Einstell. f\u00fcr das Programm indexer<\/p>\n<p>indexer<br \/>\n{<br \/>\n# Speicherlimit: hier 64 MB<br \/>\nmem_limit = 64M<br \/>\n}<\/p>\n<p>#Einstell. f\u00fcr den search-daemon<\/p>\n<p>searchd<br \/>\n{<br \/>\n# Adresse IP, auf der er lauschen soll? hier nur lokal<br \/>\naddress = 127.0.0.1<br \/>\n# Port zum lauschen? standard -&gt; 3312<br \/>\nport = 3312<br \/>\n# Pfad zur Log-Datei? (Verzeichnis muss existieren!)<br \/>\nlog = \/var\/log\/searchd.log<br \/>\n# Pfad zur Log-Datei f\u00fcr Anfragen (Verzeichnis muss existieren!)<br \/>\nquery_log = \/var\/log\/query.log<br \/>\n# Timeout in Sekunden 5<br \/>\nread_timeout = 5<br \/>\n# Maximale Zahl an Kinder-Prozessen? 30 ist OK<br \/>\nmax_children = 30<br \/>\n# Pfad zur Datei mit PID (Verzeichnis muss existieren!)<br \/>\npid_file = \/var\/run\/searchd.pid<br \/>\n# Wie viel Antworten maximal k\u00f6nnen ansgeliefert werden? 5000<br \/>\nmax_matches = 5000<br \/>\n}<br \/>\n<\/code><\/p>\n<p>Den Betrieb aufnehmen&#8230;<\/p>\n<p>Wir gehen ins \/etc (bl\u00f6der Weise muss das sein) und starten &#8222;indexer INDEXNAME&#8220; (unser Beispiel: indexer index_CONTENT). Das Programm indexer kam mit sphinx und ist f\u00fcr das Erstellen des Indexes zust\u00e4ndig. Sollte es hier Probleme geben, sind 2 Fragen zu Beantworten: Bin ich in \/etc? (indexer versucht sphinx.conf im aktuellen Verzeichnis zu lesen d.h. dort wo man grade ist -&gt; &#8222;pwd&#8220; hilft weiter) Stimmt die Konfiguration? (Stimmen die Pfade? Existieren die Verzeichnisse? Ist MySQL erreichbar? Sind Zeilenumbr\u00fcche gesch\u00fctzt mit &#8222;&#8220;? Sind die SQL-Statements OK?)<\/p>\n<p>Jetzt nur noch des Seach-Daemon mit <code>\/etc\/init.d\/searchd start<\/code> starten und wir m\u00fcssten jetzt suchen k\u00f6nnen: <code>search -c \/etc\/sphinx.conf -i INDEXNAME Suchwort<\/code> oder <code>search -i INDEXNAME Suchwort<\/code> &#8211; wenn man in \/etc ist (da sphinx.conf im aktuellen Verzeichnis gesucht wird).<\/p>\n<p>F\u00fcr das Reindexieren (Erneuern von Indexes) braucht man ein Paar Buchstaben mehr: <code>indexer --rotate INDEXNAME<\/code>. Das teilt dem Search-Daemon anschlie\u00dfend mit, dass der Index sich ver\u00e4ndert hat und neu eingelesen werden sollte&#8230;<\/p>\n<p>Sphinx als Engine in MySQL<\/p>\n<p><code>cd mysql-5.0.41<\/code><br \/>\nmit:<br \/>\n<code> patch -p1 &lt; ..\/sphinx-0.9.7\/mysqlse\/sphinx.5.0.37.diff<\/code><br \/>\npatchen wir die mysql-Quellen. Sollten hier fehler eintreten, ist m\u00e4chtig was schief gelaufen oder &#8211; was viel wahrscheinlicher ist &#8211; Du verwendest andere Versionen als ich.<\/p>\n<p>Jetzt die configurieren wir mysql f\u00fcr die Verwendung mit SPHINX als Datenbanktyp:<br \/>\n<code><br \/>\n.\/configure<br \/>\n--prefix=\/usr<br \/>\n--exec-prefix=\/usr<br \/>\n--libexecdir=\/usr\/sbin<br \/>\n--datadir=\/usr\/share<br \/>\n--localstatedir=\/var\/lib\/mysql<br \/>\n--includedir=\/usr\/include<br \/>\n--infodir=\/usr\/share\/info<br \/>\n--mandir=\/usr\/share\/man<br \/>\n--enable-shared<br \/>\n--enable-static<br \/>\n--enable-thread-safe-client<br \/>\n--enable-local-infile<br \/>\n--with-big-tables<br \/>\n--with-raid<br \/>\n--with-unix-socket-path=\/var\/run\/mysqld\/mysqld.sock<br \/>\n--with-mysqld-user=mysql<br \/>\n--with-libwrap<br \/>\n--with-vio<br \/>\n--without-openssl<br \/>\n--with-yassl<br \/>\n--without-docs<br \/>\n--with-bench<br \/>\n--without-readline<br \/>\n--with-extra-charsets=all<br \/>\n--with-innodb<br \/>\n--with-sphinx-storage-engine<br \/>\n--with-isam<br \/>\n--with-archive-storage-engine<br \/>\n--with-csv-storage-engine<br \/>\n--with-federated-storage-engine<br \/>\n--without-embedded-server<br \/>\n--with-ndbcluster<br \/>\n--with-ndb-shm<br \/>\n--without-ndb-sci<br \/>\n--without-ndb-test<br \/>\n--with-embedded-server<br \/>\n--with-embedded-privilege-control<br \/>\n--with-ndb-docs<br \/>\n<\/code><br \/>\nWichtig ist die Zeile: <code>--with-sphinx-storage-engine<\/code>, die SPHINX als storage engine mitkompiliert. Die Binaries landen &#8211; wie gew\u00fcnscht &#8211; in \/usr\/lib und \/usr\/bin. Manchmal &#8211; wie auf einem CentOS &#8211; steht auch das <code>--without-readline<\/code> im Wege. <code>--with-readline<\/code> behebt das Problem.<\/p>\n<p>Bevor wir zum make schreiten nur noch eins:<br \/>\n<code>cp -r ..\/sphinx-0.9.7\/mysqlse sql\/sphinx<\/code><\/p>\n<p>F\u00fcr gcc 4.1 muss man noch in sql\/sphinx\/ha_sphinx.cc folgendes ersetzen:<br \/>\n<code>CSphSEFilter::CSphSEFilter ()\" mit \"CSphSEFilter ()<\/code><br \/>\n<code>CSphSEFilter::~CSphSEFilter ()\" mit \"~CSphSEFilter ()<\/code><\/p>\n<p>Jetzt kommen die Macher dran: <code>make<\/code><\/p>\n<p>(Sollte es Probleme mit sql_yacc.cc geben, muss man etwas tricksen: sql\/Makefile \u00f6ffnen und &#8222;-d &#8211;debug &#8211;verbose&#8220; in &#8222;&#8211;debug &#8211;verbose&#8220; \u00e4ndern. Oder ist bison nicht installiert?)<\/p>\n<p>Jetzt m\u00fcssten die binaries fertig sein&#8230; Wir stoppen den mysql-Dienst &#8211; sofern vorhanden und l\u00e4uft &#8211; mit \/etc\/init.d\/mysql stop und rufen &#8222;make install&#8220; auf. Jetzt k\u00f6nnen wir die neue Version von mysql starten (mysql-Dienst starten z.B mit \/etc\/init.d\/mysql start). Wir loggen uns in mysql ein (<code>mysql -u Benutzername -p<\/code>) und setzen <code>show engines;<\/code> ab. In der Liste sollte SPHINX schon drin stehen.<br \/>\n<code>| SPHINX | YES | Sphinx storage engine 0.9.7 |<\/code><br \/>\nWir haben alles richtig gemacht und k\u00f6nnen uns schon mal dar\u00fcber freuen&#8230; :-) <\/p>\n<p>Jetzt k\u00f6nnen wir die Pseudo-Tabelle erstellen, die eine Verbindung zum Seach-Daemon erstellt. Sie hei\u00dft als Beispiel &#8222;t1&#8220;<br \/>\n<code><br \/>\nCREATE TABLE t1 (<br \/>\n     id          INTEGER NOT NULL,<br \/>\n     weight      INTEGER NOT NULL,<br \/>\n     query       VARCHAR(3072) NOT NULL,<br \/>\n\t group_id    INTEGER,     INDEX(query)<br \/>\n\t )<br \/>\n\t ENGINE=SPHINX CONNECTION=\"sphinx:\/\/localhost:3312\/INDEXNAME\";<br \/>\n<\/code><br \/>\nMit: <\/p>\n<p><code>SELECT * FROM t1 WHERE query='test it;mode=any';<\/code>kann man des Search-Daemon \u00fcber MySQL abfragen! Keine API mehr Notwendig! Nur Anbindung an MySQL muss funktionieren. Wie man die Anfragen Stellt, muss man jedoch selber in der Sphinx Dokumentation studieren&#8230; Ich sage nur: Alles kommt in den query=&#8220;&#8230;.&#8220;-String!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>http:\/\/www.sphinxsearch.com Sphinx Search Engine, die &#8211; wie sie sich selber nennt &#8211; &#8222;Free open-source SQL full-text search engine&#8220; ist ein gutes tool, um die Volltextsuche auf dem eigenen Server zu beschleunigen. Der Ansatz ist gut, die Ergebnisse noch besser, aber die Installation ein langer Leidensweg&#8230; Da dies \u00f6fters bei Open Source Projekten der Fall ist, muss man wohl oder \u00fcber nach Anleitungen Ausschau halten, um genau das nicht selber durchmachen zu m\u00fcssen.<br \/>\nEine solche Anleitung soll dieser Artikel sein. <\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_sitemap_exclude":false,"_sitemap_priority":"","_sitemap_frequency":"","ocean_post_layout":"","ocean_both_sidebars_style":"","ocean_both_sidebars_content_width":0,"ocean_both_sidebars_sidebars_width":0,"ocean_sidebar":"","ocean_second_sidebar":"","ocean_disable_margins":"enable","ocean_add_body_class":"","ocean_shortcode_before_top_bar":"","ocean_shortcode_after_top_bar":"","ocean_shortcode_before_header":"","ocean_shortcode_after_header":"","ocean_has_shortcode":"","ocean_shortcode_after_title":"","ocean_shortcode_before_footer_widgets":"","ocean_shortcode_after_footer_widgets":"","ocean_shortcode_before_footer_bottom":"","ocean_shortcode_after_footer_bottom":"","ocean_display_top_bar":"default","ocean_display_header":"default","ocean_header_style":"","ocean_center_header_left_menu":"","ocean_custom_header_template":"","ocean_custom_logo":0,"ocean_custom_retina_logo":0,"ocean_custom_logo_max_width":0,"ocean_custom_logo_tablet_max_width":0,"ocean_custom_logo_mobile_max_width":0,"ocean_custom_logo_max_height":0,"ocean_custom_logo_tablet_max_height":0,"ocean_custom_logo_mobile_max_height":0,"ocean_header_custom_menu":"","ocean_menu_typo_font_family":"","ocean_menu_typo_font_subset":"","ocean_menu_typo_font_size":0,"ocean_menu_typo_font_size_tablet":0,"ocean_menu_typo_font_size_mobile":0,"ocean_menu_typo_font_size_unit":"px","ocean_menu_typo_font_weight":"","ocean_menu_typo_font_weight_tablet":"","ocean_menu_typo_font_weight_mobile":"","ocean_menu_typo_transform":"","ocean_menu_typo_transform_tablet":"","ocean_menu_typo_transform_mobile":"","ocean_menu_typo_line_height":0,"ocean_menu_typo_line_height_tablet":0,"ocean_menu_typo_line_height_mobile":0,"ocean_menu_typo_line_height_unit":"","ocean_menu_typo_spacing":0,"ocean_menu_typo_spacing_tablet":0,"ocean_menu_typo_spacing_mobile":0,"ocean_menu_typo_spacing_unit":"","ocean_menu_link_color":"","ocean_menu_link_color_hover":"","ocean_menu_link_color_active":"","ocean_menu_link_background":"","ocean_menu_link_hover_background":"","ocean_menu_link_active_background":"","ocean_menu_social_links_bg":"","ocean_menu_social_hover_links_bg":"","ocean_menu_social_links_color":"","ocean_menu_social_hover_links_color":"","ocean_disable_title":"default","ocean_disable_heading":"default","ocean_post_title":"","ocean_post_subheading":"","ocean_post_title_style":"","ocean_post_title_background_color":"","ocean_post_title_background":0,"ocean_post_title_bg_image_position":"","ocean_post_title_bg_image_attachment":"","ocean_post_title_bg_image_repeat":"","ocean_post_title_bg_image_size":"","ocean_post_title_height":0,"ocean_post_title_bg_overlay":0.5,"ocean_post_title_bg_overlay_color":"","ocean_disable_breadcrumbs":"default","ocean_breadcrumbs_color":"","ocean_breadcrumbs_separator_color":"","ocean_breadcrumbs_links_color":"","ocean_breadcrumbs_links_hover_color":"","ocean_display_footer_widgets":"default","ocean_display_footer_bottom":"default","ocean_custom_footer_template":"","ocean_post_oembed":"","ocean_post_self_hosted_media":"","ocean_post_video_embed":"","ocean_link_format":"","ocean_link_format_target":"self","ocean_quote_format":"","ocean_quote_format_link":"post","ocean_gallery_link_images":"on","ocean_gallery_id":[],"footnotes":""},"categories":[8],"tags":[25,65,72,74,82,96,105],"class_list":["post-34","post","type-post","status-publish","format-standard","hentry","category-software","tag-config","tag-linux","tag-mysql","tag-opensource","tag-php","tag-server","tag-sphinx","entry"],"_links":{"self":[{"href":"https:\/\/blog.kolatzek.org\/wblog\/wp-json\/wp\/v2\/posts\/34","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.kolatzek.org\/wblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.kolatzek.org\/wblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.kolatzek.org\/wblog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.kolatzek.org\/wblog\/wp-json\/wp\/v2\/comments?post=34"}],"version-history":[{"count":0,"href":"https:\/\/blog.kolatzek.org\/wblog\/wp-json\/wp\/v2\/posts\/34\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.kolatzek.org\/wblog\/wp-json\/wp\/v2\/media?parent=34"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.kolatzek.org\/wblog\/wp-json\/wp\/v2\/categories?post=34"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.kolatzek.org\/wblog\/wp-json\/wp\/v2\/tags?post=34"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}