MySQL / PHP Эффективность поиска - PullRequest
8 голосов
/ 02 июня 2010

Я пытаюсь создать небольшой поиск для моего сайта. Я пытался использовать полнотекстовый поиск, но никогда не мог заставить его работать. Вот что я придумала:

if(isset($_GET['search'])) {

$search = str_replace('-', ' ', $_GET['search']);
$result = array();

$titles = mysql_query("SELECT title FROM Entries WHERE title LIKE '%$search%'");
while($row = mysql_fetch_assoc($titles)) {
    $result[] = $row['title'];
}

$tags = mysql_query("SELECT title FROM Entries WHERE tags LIKE '%$search%'");
while($row = mysql_fetch_assoc($tags)) {
    $result[] = $row['title'];
}

$text = mysql_query("SELECT title FROM Entries WHERE entry LIKE '%$search%'");
while($row = mysql_fetch_assoc($text)) {
    $result[] = $row['title'];
}

$result = array_unique($result);
}

Так что, в основном, он просматривает все заголовки, основной текст и теги всех записей в БД. Это работает неплохо, но мне просто интересно, насколько эффективно это будет? Это будет только для небольшого блога тоже. В любом случае, мне просто интересно, можно ли сделать это более эффективным.

Ответы [ 3 ]

22 голосов
/ 02 июня 2010

Нет способа сделать LIKE '%pattern%' эффективными запросы. Как только вы получаете нетривиальный объем данных, использование этих подстановочных запросов выполняется в сотни или тысячи раз медленнее, чем использование решения для полнотекстовой индексации.

Вы должны посмотреть на презентацию, которую я сделал для MySQL University: http://www.slideshare.net/billkarwin/practical-full-text-search-with-my-sql

Вот как заставить его работать:

  1. Сначала убедитесь, что ваша таблица использует механизм хранения MyISAM. Индексы MySQL FULLTEXT поддерживают только таблицы MyISAM. ( редактировать 01.11.2012: MySQL 5.6 представляет тип индекса FULLTEXT для таблиц InnoDB.)

    ALTER TABLE Entries ENGINE=MyISAM;
    
  2. Создание полнотекстового индекса.

    CREATE FULLTEXT INDEX searchindex ON Entries(title, tags, entry);
    
  3. Поиск!

    $search = mysql_real_escape_string($search);
    $titles = mysql_query("SELECT title FROM Entries 
        WHERE MATCH(title, tags, entry) AGAINST('$search')");
    while($row = mysql_fetch_assoc($titles)) {
        $result[] = $row['title'];
    }
    

    Обратите внимание, что столбцы, которые вы называете в предложении MATCH , должны быть такими же столбцами в том же порядке, что и те, которые вы объявили в определении полнотекстового индекса. В противном случае это не сработает.


Я пытался использовать полнотекстовый поиск по индексу, но так и не смог заставить его работать ... Мне просто интересно, можно ли сделать это более эффективным.

Это все равно, что сказать: «Я не мог понять, как пользоваться этой бензопилой, поэтому я решил срубить это красное дерево с помощью карманного ножа. Как я могу сделать так же хорошо, как бензопилу?»


Относительно вашего комментария о поиске слов, которые соответствуют более 50% строк.

В руководстве по MySQL написано this :

Пользователи, которым необходимо обойти ограничение в 50%, могут использовать логический режим поиска; см. Раздел 11.8.2, «Булевы полнотекстовые поиски» .

И это :

50% порог для естественного языка поиски определяется выбрана конкретная схема взвешивания. к отключите его, ищите следующее строка в хранилище / myisam / ftdefs.h:

# определение GWS_IN_USE GWS_PROB

Измените эту строку на:

# определение GWS_IN_USE GWS_FREQ

Затем перекомпилируйте MySQL. Нет нужды перестроить индексы в этом случае.

Кроме того, вы можете искать стоп-слов . Это слова, которые игнорируются полнотекстовым поиском, потому что они слишком распространены. Такие слова, как "и" и так далее. Смотри http://dev.mysql.com/doc/refman/5.1/en/fulltext-stopwords.html

5 голосов
/ 02 июня 2010

Использование LIKE - это НЕ полный текст.

Вам необходимо использовать ... WHERE MATCH(column) AGAINST('the query') для доступа к полнотекстовому поиску.

4 голосов
/ 02 июня 2010

MySQL Полнотекстовый поиск работает - я бы посмотрел и отладил его, а не пытался сделать это. Выполнение 3-х отдельных запросов MySQL не будет настолько эффективным.

Если вы хотите попытаться сделать это настолько эффективным, вы можете разделить операторы LIKE в одном запросе с OR между ними.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...