この目的のために、 Sphinx検索エンジンが発明されました。
ベースが大きくなるか、インデックスが大量になると、インデックスの再作成に非常に長い時間がかかり始めます。これは、プロジェクトにさまざまな悪影響を与える可能性があります。 この時点で、 デルタインデックスの使用を検討する必要があります 。
著者は、インデックスの再作成に1時間以上かかり始めたときに、このニーズに直面しました。
しかし、これらはすべてドキュメントで詳細に説明されており、非常に簡単に実行されます。
source src_mysql { type = mysql sql_host = localhost sql_user = sphinx sql_pass = secret sql_range_step = 1000 } source src_news : src_mysql { sql_db = project sql_query_pre = SET NAMES utf8 sql_query_pre = SET CHARACTER SET utf8 sql_query_pre = REPLACE INTO sph_counter SELECT 'src_news', MAX(id) FROM news sql_query_range = SELECT MIN(id), MAX(id) FROM news sql_query = SELECT id as news_id, title, content FROM news WHERE id>=$start AND id<=$end } source src_news_delta : src_news { sql_query_pre = SET NAMES utf8 sql_query_pre = SET CHARACTER SET utf8 sql_query_range = sql_query = SELECT id as news_id title, content FROM news \ WHERE id > ( SELECT max_value FROM sph_counter WHERE source = 'src_news') sql_query_post = REPLACE INTO sph_counter SELECT 'src_news', MAX(id) FROM news }
次に、複数のインデックスサーバーがある場合を考えます。 これにはいくつかの理由が考えられますが、問題が発生します。インデックスを作成した後、1つのサーバーがデータベースの最後のIDの値を上書きします。 次のサーバーでインデックス作成が開始されると、前のサーバーによってインデックスが作成されたレコードは選択に含まれません。 インデックスには「ギャップ」があり、検索結果は常に異なり、ランダムな結果は失われます。
どうする
sph_counterテーブルにインデックスサーバーIDを追加で保存する必要があります。
ホスト名列を追加します。
その結果、テーブルは次のようになります。
CREATE TABLE IF NOT EXISTS `sph_counter` ( `source` varchar(100) NOT NULL DEFAULT '', `max_value` bigint(20) NOT NULL, `hostname` varchar(50) NOT NULL DEFAULT '', PRIMARY KEY (`source`,`hostname`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
* インデックスに注意してください。REPLACEINTOを正しく動作させるために必要です。
次に、オプション2の構成に応じて:
1. Sphinxプロセスはデータベースと同じサーバーで実行され、マスターマスターレプリケーションが構成されます
この状況では、問題は非常に簡単に解決されます。グローバルMySQL変数-'hostname'を使用します
設定は次の形式を取ります。
source src_news : src_mysql { sql_db = project sql_query_pre = SET NAMES utf8 sql_query_pre = SET CHARACTER SET utf8 sql_query_pre = REPLACE INTO sph_counter SELECT 'src_news', MAX(id), @@hostname FROM news sql_query_range = SELECT MIN(id), MAX(id) FROM news sql_query = SELECT id as news_id, title, content FROM news WHERE id>=$start AND id<=$end } source src_news_delta : src_news { sql_query_pre = SET NAMES utf8 sql_query_pre = SET CHARACTER SET utf8 sql_query_range = sql_query = SELECT id as news_id, title, content FROM news \ WHERE id > ( SELECT max_value FROM sph_counter WHERE source = 'src_news' AND hostname = @@hostname) sql_query_post = REPLACE INTO sph_counter SELECT 'src_news', MAX(id), @@hostname FROM news }
2. MySQLとSphinxサーバーは異なり、リクエストはマスターに送られます
この場合、 ホスト名グローバル変数は使用できなくなります。データベースが実行されているサーバーの名前を常に取得します。
終了:接続情報とユーザー変数を使用します。
source src_news : src_mysql { sql_db = project sql_query_pre = SET NAMES utf8 sql_query_pre = SET CHARACTER SET utf8 sql_query_pre = SELECT @sphinx_instance:=IF(STRCMP(@sphinx_host:=SUBSTRING_INDEX(host,':',1),'localhost'),@sphinx_host,@@hostname) AS sphinx_instance \ FROM information_schema.processlist WHERE ID=connection_id(); sql_query_pre = REPLACE INTO sph_counter SELECT 'src_news', MAX(id), @sphinx_instance FROM news sql_query_range = SELECT MIN(id), MAX(id) FROM news sql_query = SELECT id as news_id, title, content FROM news WHERE id>=$start AND id<=$end } source src_news_delta : src_news { sql_query_pre = SET NAMES utf8 sql_query_pre = SET CHARACTER SET utf8 sql_query_pre = SELECT @sphinx_instance:=IF(STRCMP(@sphinx_host:=SUBSTRING_INDEX(host,':',1),'localhost'),@sphinx_host,@@hostname) AS sphinx_instance \ FROM information_schema.processlist WHERE ID=connection_id(); sql_query_pre = REPLACE INTO sph_counter SELECT 'src_news', MAX(id), @sphinx_instance FROM news sql_query_range = sql_query = SELECT id as news_id, title, content FROM news \ WHERE id > ( SELECT max_value FROM sph_counter WHERE source = 'src_news' AND hostname = @sphinx_instance) sql_query_post = REPLACE INTO sph_counter SELECT 'src_news', MAX(id), @sphinx_instance FROM news }
この構成は、どちらの場合でも機能します。