Вопрос

У меня есть проблема с разработкой веб-приложения, для которой я разработал одно решение, но я пытаюсь найти другие идеи, которые могли бы обойти некоторые проблемы с производительностью, которые я наблюдаю.

постановка задачи:

  • пользователь вводит несколько ключевых слов/токенов
  • приложение ищет совпадения с токенами
  • нужен один результат для каждого токена
    • т. е. если запись имеет 3 токена, мне нужен идентификатор записи 3 раза.
  • ранжировать результаты
    • назначить X очков за совпадение токенов
    • сортировать идентификаторы записей по баллам
    • если значения баллов одинаковы, используйте дату для сортировки результатов

Что я хочу сделать, но не понял, так это отправить 1 запрос, который возвращает что-то похожее на результаты in(), но возвращает повторяющийся идентификатор записи для каждого совпадения токена для каждого проверенного идентификатора записи.

Есть ли лучший способ сделать это, чем то, что я делаю, используя несколько отдельных запросов, выполняя по одному запросу на каждый токен?Если да, то какой самый простой способ это реализовать?

редактировать
Я уже токенизировал записи, поэтому, например, «см. спотовый прогон» имеет идентификатор записи 1 и три токена: «см.», «спот», «запуск», и они находятся в отдельной таблице токенов. с соответствующими им идентификаторами записей, поэтому таблица может выглядеть так:

'see', 1 
'spot', 1 
'run', 1 
'run', 2 
'spot', 3 
Это было полезно?

Решение

вы можете добиться этого в одном запросе, используя «UNION ALL» в MySQL.

Просто переберите токены в PHP, создав UNION ALL для каждого токена:

например, если токены «x», «y» и «z», ваш запрос может выглядеть примерно так

SELECT * FROM `entries` 
WHERE token like "%x%" union all 
    SELECT * FROM `entries` 
    WHERE token like "%y%" union all 
        SELECT * FROM `entries` 
        WHERE token like "%z%" ORDER BY score ect...

Предложение заказа должно работать со всем набором результатов как с одним, и это то, что вам нужно.

С точки зрения производительности это будет не так уж и быстро (я предполагаю), однако в случае с базами данных основные накладные расходы с точки зрения скорости часто связаны с отправкой запроса в механизм базы данных из PHP и получением результатов.При использовании этого метода это происходит только один раз, а не один раз для каждого токена, поэтому производительность увеличится, я просто не знаю, будет ли этого достаточно.

Другие советы

Я знаю, что это не совсем ответ на вопрос, который вы задаете. но если ваша таблица состоит из тысяч, а не миллионов строк, то решение FULLTEXT может быть лучшим вариантом.

В MySQL, когда вы используете ПОИСКПОЗ в своем индексированном столбце, каждому введенному вами ключевому слову будет присвоен показатель релевантности (рассчитанный примерно по количеству упоминаний каждого ключевого слова), который будет более точным, чем ваш метод, и, безусловно, более эффективным для нескольких ключевых слов.

Глянь сюда:http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html

Если вы используете шаблон UNION ALL, вы также можете включить в свой запрос следующие части:

SELECT COUNT(*) AS C
...
GROUP BY ID
ORDER BY c DESC

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

Вероятно, вы добьетесь гораздо большей производительности, если будете использовать структуру данных, предназначенную для задач поиска, а не базу данных.Например, вы можете попытаться построить инвертированный индекс.Однако вместо того, чтобы писать это самостоятельно, вы также можете изучить что-то вроде Лусене который делает большую часть работы за вас.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top