Любой способ добиться полнотекстового поиска в InnoDB
У меня очень простой запрос:
SELECT ... WHERE row LIKE '%some%' OR row LIKE '%search%' OR row LIKE '%string%'
искать some search string
, но, как вы можете видеть, он ищет каждую строку в отдельности, и это также не очень хорошо для производительности.
Есть ли способ воссоздать полнотекстовый поиск, используя LIKE для таблицы InnoDB. Конечно, я знаю, что могу использовать что-то вроде Sphinx для достижения этой цели, но я ищу чистое решение MySQL.
3 ответа
Используйте полнотекстовую таблицу myisam для индексации ваших таблиц innodb, например:
Создайте свою систему, используя innodb:
create table users (...) engine=innodb;
create table forums (...) engine=innodb;
create table threads
(
forum_id smallint unsigned not null,
thread_id int unsigned not null default 0,
user_id int unsigned not null,
subject varchar(255) not null, -- gonna want to search this... !!
created_date datetime not null,
next_reply_id int unsigned not null default 0,
view_count int unsigned not null default 0,
primary key (forum_id, thread_id) -- composite clustered PK index
)
engine=innodb;
Теперь таблица полнотекстового поиска, которую мы будем использовать для индексации наших таблиц innodb. Вы можете поддерживать строки в этой таблице, используя триггер или ночные пакетные обновления и т. Д.
create table threads_ft
(
forum_id smallint unsigned not null,
thread_id int unsigned not null default 0,
subject varchar(255) not null,
fulltext (subject), -- fulltext index on subject
primary key (forum_id, thread_id) -- composite non-clustered index
)
engine=myisam;
Наконец, поиск хранимой процедуры, которую вы вызываете из вашего php/ приложения:
drop procedure if exists ft_search_threads;
delimiter #
create procedure ft_search_threads
(
in p_search varchar(255)
)
begin
select
t.*,
f.title as forum_title,
u.username,
match(tft.subject) against (p_search in boolean mode) as rank
from
threads_ft tft
inner join threads t on tft.forum_id = t.forum_id and tft.thread_id = t.thread_id
inner join forums f on t.forum_id = f.forum_id
inner join users u on t.user_id = u.user_id
where
match(tft.subject) against (p_search in boolean mode)
order by
rank desc
limit 100;
end;
call ft_search_threads('+innodb +clustered +index');
Надеюсь это поможет:)
Использование PHP для построения запроса. Это ужасный хак. Однажды увиденное, это не может быть невидимым...
$words=dict($userQuery);
$numwords = sizeof($words);
$innerquery="";
for($i=0;$i<$numwords;$i++) {
$words[$i] = mysql_real_escape_string($words[$i]);
if($i>0) $innerquery .= " AND ";
$innerquery .= "
(
field1 LIKE \"%$words[$i]%\" OR
field2 LIKE \"%$words[$i]%\" OR
field3 LIKE \"%$words[$i]%\" OR
field4 LIKE \"%$words[$i]%\"
)
";
}
SELECT fields FROM table WHERE $innerquery AND whatever;
dict - это словарная функция
Полнотекстовый поиск InnoDB (FTS) наконец доступен в выпуске MySQL 5.6.4.
Эти индексы физически представляются в виде целых таблиц InnoDB, на которые действуют ключевые слова SQL, такие как предложение FULLTEXT оператора CREATE INDEX, синтаксис MATCH() ... AGAINST в операторе SELECT и оператор OPTIMIZE TABLE. Из полных текстовых индексов