#mysql #json #full-text-search #innodb #generated
Вопрос:
Стол:
CREATE TABLE `stores` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`slug` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
`value` json DEFAULT NULL,
`html` mediumtext COLLATE utf8mb4_unicode_ci
GENERATED ALWAYS AS (json_unquote(json_extract(`value`,'$.html')))
STORED,
PRIMARY KEY (`id`),
KEY `slug` (`slug`),
FULLTEXT KEY `html` (`html`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
Запрос:
select id from `stores` where MATCH(stores.html) AGAINST ('forum*' IN BOOLEAN MODE) limit 20
Занимает 0,14 секунды
Объяснять:
ID | select_type | стол | перегородки | Тип | возможные ключи | Клавиша | key_len | ссылка | строки | отфильтровано | Дополнительный |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | простой | Магазины | нулевой | полный текст | HTML | HTML | 0 | конст | 1 | 100.00 | Использование where; Ft_hints: без ранжирования, ограничение = 20 |
Когда запрос:
select id from `stores` where stores.html like '%forum%' limit 20
Занимает всего 0,003 секунды
Объяснять:
ID | select_type | стол | перегородки | Тип | возможные ключи | Клавиша | key_len | ссылка | строки | отфильтровано | Дополнительный |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | простой | Магазины | нулевой | ВСЕ | нулевой | нулевой | нулевой | нулевой | 134101 | 100.00 | Используя где |
Я помню, когда я впервые реализовал эти виртуальные сгенерированные поля через json, это казалось быстрее, чем хотелось бы, но теперь, после реализации этого по всем полям, я заметил, что сайт стал медленнее. Поэтому я начал анализировать простые запросы и обнаружил, что полный текст на самом деле значительно медленнее!
Когда я добавляю SQL_NO_CACHE после выбора, это не имеет значения.
Чего мне не хватает? Спасибо
Комментарии:
1. Удалите
LOWER
его ; это может пойти еще быстрее.2. Вы получаете те же результаты?
3. По состоянию на БОЛЕЕ НИЗКОЕ удаление, хорошо, но вопрос в том, почему полнотекстовый поиск выполняется медленно? Те же результаты? С помощью LIKE я получаю немного большее количество результатов, потому что он соответствует строке, даже если она является частью другого слова.
4. Сколько времени это займет?
SELECT MAX(LENGTH(html)) FROM stores where html like '%forum%';
?5. МАКС. (ДЛИНА(html)) 75581 1 строка (0,083 с)
Ответ №1:
Этот запрос выполняется аномально быстро:
select id from `stores`
where stores.html like '%forum%' limit 20
Потому что он просмотрел только достаточное количество строк, чтобы найти 20, в которых была эта строка. Я думаю, вы обнаружите, что это займет значительно больше времени, так как он будет проверять каждую строку:
select id from `stores`
where stores.html like '%non-existent-text%' limit 20
Другая возможная причина заключается в том, что MATCH
были найдены сотни, может быть, тысячи строк или строк, прежде чем он приступил к выполнению LIMIT
. Так что время это:
select id from `stores`
where MATCH(stores.html) AGAINST ('qwertyui' IN BOOLEAN MODE) limit 20
Суть в том, что вам, возможно, придется смириться с такими несоответствиями. Я верю (без веских доказательств вашего набора данных), что MATCH
обычно будет быстрее, чем LIKE
. Обратите внимание на слово «обычно».