В настоящее время я пытаюсь выполнить несколько запросов к дампу данных комментариев переполнения стека. Вот как выглядит схема:
CREATE TABLE `socomments` (
`Id` int(11) NOT NULL,
`PostId` int(11) NOT NULL,
`Score` int(11) DEFAULT NULL,
`Text` varchar(600) NOT NULL,
`CreationDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`UserId` int(11) NOT NULL,
PRIMARY KEY (`Id`),
KEY `idx_socomments_PostId` (`PostId`),
KEY `CreationDate` (`CreationDate`),
FULLTEXT KEY `Text` (`Text`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
Я выполнил этот запрос к таблице, и он работал невероятно медленно (у него есть 29 миллионов строк, но у него есть полнотекстовый индекс):
SELECT *
FROM socomments
WHERE MATCH (Text) AGAINST ('"fixed the post"' IN BOOLEAN MODE)
Итак, я его профилировал, результаты которого таковы:
|| Status || Duration ||
|| starting || 0.000058 ||
|| checking permissions || 0.000006 ||
|| Opening tables || 0.000014 ||
|| init || 0.000019 ||
|| System lock || 0.000006 ||
|| optimizing || 0.000007 ||
|| statistics || 0.000013 ||
|| preparing || 0.000005 ||
|| FULLTEXT initialization || 207.1112 ||
|| executing || 0.000009 ||
|| Sending data || 0.000856 ||
|| end || 0.000004 ||
|| query end || 0.000004 ||
|| closing tables || 0.000006 ||
|| freeing items || 0.000059 ||
|| logging slow query || 0.000037 ||
|| cleaning up || 0.000046 ||
Как видите, он долго тратит на инициализацию FULLTEXT. Это нормально? Если нет, то как бы это исправить?
mysql
innodb
full-text-search
hichris123
источник
источник
id_group 2
иid_group 23
. С этим ваш поиск внутри вашей основной таблицы и ограничить ваш запрос диапазонами идентификаторов от 2.000 до 2.999 и от 23.000 до 23.999. Конечно, 2-й будет давать больше результатов по мере необходимости, поскольку вы смешиваете все комментарии, создавая новые комбинации ключевых слов, но, наконец, это должно ускорить все это. Конечно, это удваивает использование дискового пространства. Новые комментарии должны быть связаны с таблицей групп.Ответы:
Другие нашли эту неприятную ситуацию
Поскольку документация MySQL очень краткая в этом состоянии потока
ваш единственный выход - сделать подготовку с меньшим количеством данных. Как ?
ПРЕДЛОЖЕНИЕ № 1
Посмотрите на ваш запрос еще раз. Он выбирает все столбцы. Я бы рефакторинг запроса, чтобы собрать только столбцы id из
socomments
. Затем присоедините полученные идентификаторы кsocomments
таблице.Это может привести к уродливому плану EXPLAIN, но я думаю, что профилирование изменится к лучшему. Основная идея такова: если у вас агрессивный поиск FULLTEXT, сделайте так, чтобы он собирал наименьшее количество данных на этом
FULLTEXT initialization
этапе, что сокращает время.Я рекомендовал это много раз, прежде чем
May 14, 2012
: медленный запрос с полным текстом и левым соединениемMar 18, 2012
: Почему LIKE более чем в 4 раза быстрее, чем MATCH ... ПРОТИВ индекса FULLTEXT в MySQL?Jan 26, 2012
: Mysql полнотекстовый поиск my.cnf оптимизация :Oct 25, 2011
: Индекс FULLTEXT игнорируется в BOOLEAN MODE с условным числом словПРЕДЛОЖЕНИЕ № 2
Убедитесь, что вы устанавливаете параметры FULLTEXT на основе InnoDB, а не параметры MyISAM. Вы должны быть обеспокоены двумя вариантами:
Задумайтесь об этом на мгновение. Текстовое поле VARCHAR (600). Скажем, среднее значение составляет 300 байт. У вас есть 29 000 000 миллионов из них. Это было бы, что было бы немного 8 ГБ. Возможно, также могут помочь увеличение innodb_ft_cache_size и innodb_ft_total_cache_size .
Убедитесь, что у вас достаточно оперативной памяти для больших буферов InnoDB FULLTEXT.
ДАЙТЕ ЭТО ПОПРОБУЙТЕ !!!
источник
SELECT B.* FROM (SELECT id FROM socomments WHERE MATCH (Text) AGAINST ('+"fixed the post"' IN BOOLEAN MODE)) A LEFT JOIN socomments B USING (id);
и посмотрите, имеет ли это значение.A leading or trailing plus sign indicates that this word must be present in each row that is returned. InnoDB only supports leading plus signs.
в вашем конкретном случаеfixed the post
должна существовать точная фраза .Если вы используете индексы InnoDB FULLTEXT, запросы часто зависают в состоянии «инициализация FULLTEXT», если вы выполняете запросы к таблице с большим количеством удаленных строк. В реализации InnoDB FULLTEXT удаленные строки не удаляются до тех пор, пока не будет запущена последующая операция OPTIMIZE для уязвимой таблицы. См .: https://dev.mysql.com/doc/refman/5.6/en/innodb-fulltext-index.html.
Можно также проверить количество удаленных, но не очищенных записей, запросив информацию_schema.innodb_ft_deleted
Для решения этой проблемы следует регулярно запускать OPTIMIZE TABLE для таблиц с индексами InnoDB FULLTEXT.
источник
innodb_optimize_fulltext_only=1
иOPTIMIZE
таблица действительно заботится об удаленных строках «в ожидании»? dba.stackexchange.com/questions/174486/…В MySQL существует подтвержденная ошибка ( удаленные DOCID не поддерживаются во время ОПТИМИЗАЦИИ таблиц InnoDB FULLTEXT ), что приводит к повышению производительности при больших нагрузках удаления (без восстановления таблицы с нуля).
Относящиеся .
источник
Полнотекстовые индексы в MySQL не предназначены для поддержки больших объемов данных, поэтому скорость поиска снижается довольно быстро по мере роста набора данных. Одним из решений является использование внешних полнотекстовых поисковых систем, таких как Solr или Sphinx, которые имеют улучшенные функциональные возможности поиска (настройка релевантности и поддержка поиска по фразам, встроенные фасеты, фрагменты и т. Д.), Расширенный синтаксис запросов и значительно более высокую скорость в середине-до -большой набор данных.
Solr основан на платформе Java, поэтому, если вы запускаете приложение на основе Java, это будет естественным выбором для вас, Sphinx написан на C ++ и действует как демон в той же манере, что и MySQL. Как только вы наполняете внешний движок данными, которые вы хотите найти, вы также можете удалить некоторые запросы из MySQL. Я не могу сказать вам, какой движок лучше в вашем случае, я использую в основном Sphinx, и вот пример использования: http://astellar.com/2011/12/replacing-mysql-full-text-search-with-sphinx/
источник