MySQL: оптимизация поиска с помощью LIKE или FULLTEXT - PullRequest
2 голосов
/ 17 августа 2011

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

SELECT users.id, users.user_name, users.user_picture
FROM users, subject1, subject2
WHERE users.id = subject1.user_id
AND users.id = subject2.user_id
AND (users.user_name LIKE '%{$keywords}%'
OR subject1.title1 LIKE '%{$keywords}%'
OR subject2.title2 LIKE '%{$keywords}%')
ORDER BY users.user_name ASC
LIMIT 10
OFFSET {$offset}

ПРЕДЕЛ и СМЕЩЕНИЕ предназначены для нумерации страниц.Мой вопрос заключается в том, будет ли выполнение поиска LIKE по нескольким таблицам значительно замедлять производительность, когда число строк достигает значительного количества?

У меня есть несколько альтернатив: во-первых, возможно, я могу переписать этот запрос, чтобы поиск LIKE выполнялся внутри подзапроса, который возвращает только индексированные user_ids.Затем я нашел бы оставшуюся информацию пользователя на основе этого.Повысит ли это производительность на много?Таким образом, я могу индексировать столбцы user_name, title1, and title2.Однако, поскольку здесь я буду торговать точностью за скорость, насколько это повлияет на производительность?Стоит ли жертвовать такой точностью для индексации этих столбцов?

В-третьих, возможно, я могу дать пользователям 3 поля поиска на выбор, и каждое из них будет вести поиск только по одной таблице.Значительно ли это увеличит производительность?

Наконец, стоит ли мне использовать поиск FULLTEXT вместо LIKE?Каковы различия в производительности между этими двумя?Кроме того, в моих таблицах используется механизм хранения InnoDB, и я не могу использовать индекс FULLTEXT, пока не переключусь на MyISAM.Будут ли какие-либо существенные различия при переходе на MyISAM?

Разбиение на страницы - это еще одна проблема производительности, о которой я беспокоюсь, потому что для разбивки на страницы мне нужно найти общее количество результатов, возвращаемых запросом.На данный момент я в основном делаю запрос, который я только что упомянул ДВАЖДЫ, потому что в первый раз он используется только для COUNT результатов.

Ответы [ 4 ]

3 голосов
/ 17 августа 2011

В вашем запросе есть две вещи, которые не позволят MySql использовать индексы, во-первых, ваши шаблоны начинаются с подстановочного знака %, MySql не может использовать индексы для поиска шаблонов, начинающихся с подстановочного знака, во-вторых, у вас есть OR в вашем предложении WHERE вам нужно переписать ваш запрос, используя UNION, чтобы избежать использования OR, что также не позволяет MySql использовать индексы. Без использования индекса MySql должен каждый раз выполнять полное сканирование таблицы, и время, необходимое для этого, будет линейно увеличиваться по мере увеличения числа строк в вашей таблице, и да, если вы скажете «это», это значительно снизит производительность, когда число строк достичь значительного количества ", поэтому я бы сказал, что единственный реальный масштабируемый вариант - использовать поиск FULLTEXT.

1 голос
/ 17 августа 2011

Большинство ваших вопросов объясняются здесь: http://use -the-index-luke.com / sql / where-clause / search-for-range / like-performance-tuning

Объявлена ​​индексация InnoDB / fulltext для MySQL 5.6, но это, вероятно, сейчас вам не поможет.

0 голосов
/ 17 августа 2011

Переключение на MyISAM должно работать без проблем. Единственным недостатком является то, что MyISAM блокирует всю таблицу при вставках / обновлениях, что может замедлять таблицы с гораздо большим количеством вставок, чем выбирает. На мой взгляд, практическое правило заключается в использовании MyISAM, когда вам не нужны внешние ключи и таблица имеет гораздо больше операций выбора, чем вставки, и использовании InnoDB, когда в таблице гораздо больше операций вставки / обновления, чем операций выбора (например, для таблицы статистики). ,

В вашем случае я думаю, что переключение на MyISAM - лучший выбор, так как полнотекстовый индекс намного мощнее и быстрее.

Это также дает возможность использовать определенные модификаторы запросов, например исключая слова ("cat -dog") или аналогичные. Но имейте в виду, что поиск слов, заканчивающихся на фразе, больше невозможен, как в LIKE-поиске ("*bar"). "foo*" будет работать, хотя.

0 голосов
/ 17 августа 2011

Как насчёт начать с EXPLAIN <select-statement>?http://dev.mysql.com/doc/refman/5.6/en/explain.html

...