ユーザーのメッセージに対して部分的な単語検索を行うスクリプトを書いています。各会話にはmail_idがあり、個々のメッセージにはmsg_idがあります。
メッセージ内の各単語の行を含むテーブルmail_word_indexがあります。
CREATE TABLE IF NOT EXISTS `mail_word_index` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`sender_id` int(10) unsigned NOT NULL DEFAULT '0',
`dest_id` int(10) unsigned NOT NULL DEFAULT '0',
`mail_id` int(10) unsigned NOT NULL DEFAULT '0',
`msg_id` int(10) unsigned NOT NULL DEFAULT '0',
`word` varchar(15) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY `dest_id` (`dest_id`,`word`),
KEY `sender_id` (`sender_id`,`word`),
KEY `multiple_words` (`mail_id`,`msg_id`,`word`)
) ENGINE=MyISAM ;
完了するまでに0.01秒かかるクエリがあります
SELECT DISTINCT w1.mail_id FROM mail_word_index AS w1,
mail_word_index AS w2
WHERE w1.sender_id=1
AND w1.word LIKE 'str%'
AND w1.mail_id=w2.mail_id
AND w1.msg_id=w2.msg_id
AND w2.word LIKE 'con%' LIMIT 20
ただし、一度に1つの単語を検索すると、各単語を完了するのに0.002秒しかかからず、合計で0.004秒かかります。
SELECT DISTINCT w1.mail_id FROM mail_word_index AS w1
WHERE w1.sender_id=1 AND w1.word LIKE 'str%' LIMIT 20
SELECT DISTINCT w1.mail_id FROM mail_word_index AS w1
WHERE w1.sender_id=1 AND w1.word LIKE 'con%' LIMIT 20
内部結合は最初のクエリの速度を低下させるようです。最初のクエリを変更して高速化するにはどうすればよいですか?
EXPLAINは私にこれを教えてくれます:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE w1 range sender_id,multiple_words sender_id 21 NULL 1 Using where; Using temporary
1 SIMPLE w2 ref multiple_words multiple_words 8 game-node4.w1.mail_id,game-node4.w1.msg_id 8 Using where; Using index; Distinct