Полнотекстовый поиск MySQL InnoDB по СОХРАНЕННОМУ столбцу, сгенерированному в формате JSON, выполняется медленнее, чем, НАПРИМЕР

#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 . Обратите внимание на слово «обычно».