This is based on some sample caching code I found on the Sphinx forum and works with Sphinx V2.02 and the Sphinx PHP API. Updates I made:
I changed the mysql database to use a varchar for the request, and added an index to it. The blob had scaling issues almost immediately. I also added a log to watch the cache at work. The log file needs to be writable by Apache ( or your web server ) and be located in the sphinx/var/log/ directory. It currently lacks any cleanup of old or unused cache entries.
My Sphinx setup is using a sharded index performing 20-40 queries per second across ~50M documents at peak times. This simple MySQL-based caching is being used as a temporary fix to some scaling issues we've encountered on a site called Industry Cortex, a research tool for the manufacturing industry. It's working pretty well for the time being, and could be a very effective and simple caching solution on the right systems with the right needs.
How to install this:
Replace the entire RunQueries() method in the Sphinx PHP api. Update the username and password to connect to MySQL using MySQLi on line 27 below. Create the mysql database ( mine is called `sphinx_cache` ) and create the `sphinx_cache` table ( same name as the database ) with the sql code below. Then create your log file and give your webserver write permissions on it. You should now have a working Sphinx cache.
Sphinx API updates:
function RunQueries () { if ( empty($this->_reqs) ) { $this->_error = "no queries defined, issue AddQuery() first"; return false; } // mbstring workaround $this->_MBPush (); if (!( $fp = $this->_Connect() )) { $this->_MBPop (); return false; } // send query, get response $nreqs = count( $this->_reqs ); $req = join ( "", $this->_reqs ); $len = 8 + strlen( $req ); $req = pack ( "nnNNN", SEARCHD_COMMAND_SEARCH, VER_COMMAND_SEARCH, $len, 0, $nreqs ) . $req; // add header // === BEGIN CACHE EDITS === $mysqli = new mysqli( 'localhost', 'username', 'password', 'sphinx_cache' ); $cache_log = '/data/sphinx/var/log/cache.log'; // check for query in mysql cache $cache_query_start = microtime( true ); $results = $mysqli->query( "SELECT response FROM sphinx_cache WHERE request='" . $mysqli->real_escape_string( $req ) . "'" ); $cache_query_end = microtime( true ); $cache_query_time = $cache_query_end - $cache_query_start; if( $results->num_rows > 0 ) { // there is a cached result // use cached result $row = $results->fetch_row( ); $response = $row[0]; // write cache hit to log file_put_contents( $cache_log, " cached query served, $cache_query_time, " . date('Y-m-d h:m:s') . ', ' . $_SERVER['PHP_SELF'] . ', ' . $_SERVER['REMOTE_ADDR'] . "\n", FILE_APPEND ); } else { // no cached result // query sphinx $sphinx_query_start = microtime( true ); if ( !( $this->_Send ( $fp, $req, $len+8 ) ) || !( $response = $this->_GetResponse ( $fp, VER_COMMAND_SEARCH ) ) ) { $this->_MBPop ( ); return false; } $sphinx_query_end = microtime( true ); $sphinx_query_time = $sphinx_query_end - $sphinx_query_start; // store new result into mysql cache $mysqli->query( "INSERT INTO sphinx_cache (request, response) VALUES ('" . $mysqli->real_escape_string( $req ) . "','" . $mysqli->real_escape_string( $response ) . "')"); // write cache miss to log file_put_contents( $cache_log, "* sphinx query served, $sphinx_query_time, " . date('Y-m-d h:m:s') . ', ' . $_SERVER['PHP_SELF'] . ', ' . $_SERVER['REMOTE_ADDR'] . "\n", FILE_APPEND ); } // === END CACHE EDITS === // query sent ok; we can reset reqs now $this->_reqs = array (); // parse and return response return $this->_ParseSearchResponse ( $response, $nreqs ); }
SQL code to generate the caching database
My database is called sphinx_cache ... the same as the table.
CREATE TABLE `sphinx_cache` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `request` varchar(5000) NOT NULL DEFAULT '', `response` text NOT NULL, `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `request` (`request`(333)) ) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;