С точки зрения производительности, насколько эффективно использовать временную таблицу MySQL для высоко используемой функции веб-сайта?
Я пытаюсь написать функцию поиска для веб-сайта, и я решил использовать временные таблицы MySQL для обработки ввода данных с помощью запроса ниже:
CREATE TEMPORARY TABLE `patternmatch`
(`pattern` VARCHAR(".strlen($queryLengthHere)."))
INSERT INTO `patternmatch` VALUES ".$someValues
здесь $someValues
- это набор данных с макетом ('some', 'search', 'query')
- или в основном то, что пользователь искал. Затем я ищу свою главную таблицу images
на основе данных в таблице patternmatch
вот так:
SELECT images.* FROM images JOIN patternmatch ON (images.name LIKE patternmatch.pattern)
затем я применяю эвристическую или систему подсчета очков, основанную на том, насколько хорошо каждый результат соответствовал входу и отображал результаты с помощью этой эвристики и т. д.
мне интересно, сколько накладных расходов требует создание временной таблицы? Я понимаю, что они существуют только в сеансе и удаляются, как только сеанс заканчивается, но если у меня есть сотни тысяч поисков в секунду, с какими проблемами производительности я могу столкнуться? Есть ли лучший способ реализации функции поиска?
3 ответов
то, что вы указали, совершенно правильно, временная таблица будет видна только текущему пользователю/соединению. Тем не менее, есть некоторые накладные расходы и некоторые другие проблемы, такие как:
- для каждого из тысяч поисков, которые вы собираетесь создать и заполнить эту таблицу (и удалить ее позже) - не для каждого пользователя, для поиска. Поскольку каждый поиск, скорее всего, будет повторно выполнять скрипт, а "за сеанс" не означает сеанс PHP - это означает сеанс базы данных (open соединение.)
- вам понадобится
CREATE TEMPORARY TABLES
привилегии, которые вы может нет. - тем не менее, эта таблица действительно должна иметь тип памяти, который крадет вашу ОЗУ больше, чем кажется. Потому что даже имея VARCHAR, таблицы памяти используют хранилище строк фиксированной длины.
- если ваша эвристика позже должна ссылаться на эту таблицу дважды (например,
SELECT xyz FROM patternmatch AS pm1, patternmatch AS pm2 ...
) - это невозможно с таблицами памяти.
далее, это было бы проще для вас - а также для базы данных-добавить LIKE '%xyz%'
непосредственно на images
таблицы WHERE
предложения. Он будет делать то же самое без накладных расходов на создание временной таблицы и присоединение к ней.
в любом случае - неважно, в какую сторону вы идете-то, где будет ужасно медленно. Даже если вы добавите индекс на images.name
вам скорее всего понадобится LIKE '%xyz%'
вместо LIKE 'xyz%'
, так что индекс не привыкать.
Я спрашиваю, является ли временная таблица конкретной сессии для обработки поисковый ввод пользователем (созданный при поиске, отброшенный в конце сеанса) является подходящим способом обработки функции поиска.
нет. :)
альтернативные варианты
MySQL имеет встроенный Полнотекстовый-Поиск (С 5.6 также для InnoDB), что даже может дать вам этот счет: я настоятельно рекомендую дать ему прочитать и попробовать. Вы можете быть уверены, что база данных знает лучше вас, как сделать этот поиск эффективно.
если вы собираетесь использовать MyISAM вместо InnoDB, имейте в виду часто упускаемое ограничение, что полнотекстовые поиски возвращают только что-либо, если количество результатов меньше 50% от общего числа строк таблицы.
другие вещи, которые вы, возможно, захотите посмотреть, например, Solr (хорошее введение, прочитанное на эту тему, будет началом http://en.wikipedia.org/wiki/Apache_Solr). Мы используем его в нашей компании и он делает отличная работа, но она требует некоторого обучения.
резюме
решение вашей текущей проблемы (поиск) заключается в использовании полнотекстовых возможностей.
если у меня сотни тысяч поисков в секунду, какие проблемы с производительностью могут возникнуть? Есть ли лучший способ реализации функции поиска?
чтобы дать вам номер, 10.000 звонков в секунду не является " тривиальным" уже-с сотнями тысяч поисков в секунду проблемы с производительностью, с которыми вы столкнетесь, повсюду в вашей настройке. Вам понадобится пара серверов, балансировка нагрузки и тонны другого удивительного технологического дерьма. И одним из них будет, например, Solr;)
- создание временных таблиц на диске относительно дорого. В вашем сценарии это звучит так, как будто это будет медленнее, чем стоит.
- обычно стоит только создавать временные таблицы в памяти. Но вы должны знать, что у вас достаточно памяти, доступной в любое время. Если вы планируете поддерживать так много поисков в секунду, это не является хорошим решением.
- MySQL есть полнотекстовый поиск встроенный. Это хорошо для небольших систем. Это, вероятно, выполните гораздо лучше, чем ваш temp таблицы и присоединиться. Но если вы хотите поддержать тысячи запросов в секунду я бы не советовал. Это может потреблять слишком много вашей общей производительности базы данных. Кроме того, вы вынуждены использовать MyISAM для хранения, которое может иметь свои собственные проблемы в вашем сценарии.
- для стольких поисков вы захотите выгрузить работу в другую систему. Уже существует множество поисковых систем со скорингом. Взгляните на ElasticSearch, Solr / Lucene, Redis, так далее.
из кода, который вы даете, я действительно не думаю, что нужны таблицы tmp, а также полнотекстовый поиск. Но... о производительности таблицы tmp:
создание / очистка таблицы tmp не записывается в журналы транзакций,поэтому ОС будет относительно быстро выполнять ввод-вывод. Если временные таблицы будут маленькими и недолговечными, и у вас есть много буферов, доступных для ОС, диск реально даже не будет затронут. Если вы думаете, что это будет в любом случае, получите SSD драйв, и получить больше ОЗУ.
но если вы реалистичны, что вы смотрите на сотни тысяч запросов в секунду!--7--> тогда у вас есть большой инженерный проект на руках. Почему бы просто не сделать:
select images.* from images where name in ('some', 'search', 'query')
?