Индекс FULLTEXT занимает больше времени для выполнения
Следующий запрос занимает 1.1 с, EXPLAIN
показывает использование FULLTEXT
индекс:
SELECT SQL_NO_CACHE COUNT(*)
FROM e_entity
WHERE meta_oid=336799 AND MATCH(sIndex07) AGAINST ("#UPR-1393#" IN NATURAL LANGUAGE MODE)
EXPLAIN:
id: 1
select_type: SIMPLE
table: e_entity
type: fulltext
possible_keys: App_Parent,sindex07
key: sIndex07
key_len: 0
ref: (NULL)
rows: 1
extra: Using Where
Есть FULLTEXT
индекс на sIndex07
колонка. Однако когда это FULLTEXT
индекс удаляется и заменяется обычным KEY
Индекс затем запрос:
SELECT SQL_NO_CACHE COUNT(*)
FROM e_entity
WHERE meta_oid=336799 AND sIndex07 LIKE "%#UPR-1393#%"
EXPLAIN:
id: 1
select_type: SIMPLE
table: e_entity
type: ref
possible_keys: App_Parent
key: App_Parent
key_len: 4
ref: const
rows: 331283
extra: Using Where
CREATE TABLE `e_entity` (
`OID` int(11) NOT NULL AUTO_INCREMENT,
`E_E_OID` int(11) DEFAULT NULL,
`UNIQUE_IDX` int(11) NOT NULL,
`APP_OID` int(11) NOT NULL,
`META_OID` int(11) NOT NULL,
`STORE_DATE` datetime NOT NULL,
`REL_DISPLAY` varchar(1024) NOT NULL,
`sIndex01` varchar(1024) NOT NULL,
`SINDEX02` varchar(1024) NOT NULL,
`SINDEX03` varchar(1024) NOT NULL,
`SINDEX04` varchar(1024) NOT NULL,
`SINDEX05` varchar(1024) NOT NULL,
`SINDEX06` varchar(1024) NOT NULL,
`sIndex07` varchar(1024) NOT NULL,
`SINDEX08` varchar(1024) NOT NULL,
`SINDEX09` varchar(1024) NOT NULL,
`sIndex10` varchar(1022) NOT NULL,
`SINDEX11` varchar(1024) NOT NULL,
`SINDEX12` varchar(1024) NOT NULL,
`SINDEX13` varchar(1024) NOT NULL,
`SINDEX14` varchar(1024) NOT NULL,
`sIndex15` varchar(1022) NOT NULL,
`SINDEX16` varchar(1024) NOT NULL,
`SINDEX17` varchar(1024) NOT NULL,
`SINDEX18` varchar(1024) NOT NULL,
`SINDEX19` varchar(1024) NOT NULL,
`SINDEX20` varchar(1024) NOT NULL,
`NINDEX01` double NOT NULL,
`NINDEX02` double NOT NULL,
`NINDEX03` double NOT NULL,
`NINDEX04` double NOT NULL,
`NINDEX05` double NOT NULL,
`NINDEX06` double NOT NULL,
`NINDEX07` double NOT NULL,
`NINDEX08` double NOT NULL,
`NINDEX09` double NOT NULL,
`NINDEX10` double NOT NULL,
`DINDEX01` datetime NOT NULL,
`DINDEX02` datetime NOT NULL,
`DINDEX03` datetime NOT NULL,
`DINDEX04` datetime NOT NULL,
`DINDEX05` datetime NOT NULL,
`DINDEX06` datetime NOT NULL,
`DINDEX07` datetime NOT NULL,
`DINDEX08` datetime NOT NULL,
`DINDEX09` datetime NOT NULL,
`DINDEX10` datetime NOT NULL,
`FREETEXT` mediumtext NOT NULL,
`UID` int(11) DEFAULT NULL,
PRIMARY KEY (`OID`),
KEY `E_E_OID` (`E_E_OID`),
KEY `sIndex01` (`SINDEX01`),
KEY `sIndex02` (`SINDEX02`),
KEY `sIndex03` (`SINDEX03`),
KEY `sIndex04` (`SINDEX04`),
KEY `sIndex05` (`SINDEX05`),
KEY `sIndex06` (`SINDEX06`),
FULLTEXT `sIndex07` (`SINDEX07`),
KEY `sIndex08` (`SINDEX08`),
KEY `sIndex09` (`SINDEX09`),
KEY `sIndex10` (`SINDEX10`),
KEY `sIndex11` (`SINDEX11`),
KEY `sIndex12` (`SINDEX12`),
KEY `sIndex13` (`SINDEX13`),
KEY `sIndex14` (`SINDEX14`),
KEY `sIndex15` (`SINDEX15`),
KEY `sIndex16` (`SINDEX16`),
KEY `sIndex17` (`SINDEX17`),
KEY `sIndex18` (`SINDEX18`),
KEY `sIndex19` (`SINDEX19`),
KEY `sIndex20` (`SINDEX20`),
KEY `dIndex01` (`DINDEX01`),
KEY `dIndex02` (`DINDEX02`),
KEY `dIndex03` (`DINDEX03`),
KEY `dIndex04` (`DINDEX04`),
KEY `dIndex05` (`DINDEX05`),
KEY `dIndex06` (`DINDEX06`),
KEY `dIndex07` (`DINDEX07`),
KEY `dIndex08` (`DINDEX08`),
KEY `dIndex09` (`DINDEX09`),
KEY `dIndex10` (`DINDEX10`),
KEY `nIndex01` (`NINDEX01`),
KEY `nIndex02` (`NINDEX02`),
KEY `nIndex03` (`NINDEX03`),
KEY `nIndex04` (`NINDEX04`),
KEY `nIndex05` (`NINDEX05`),
KEY `nIndex06` (`NINDEX06`),
KEY `nIndex07` (`NINDEX07`),
KEY `nIndex08` (`NINDEX08`),
KEY `nIndex09` (`NINDEX09`),
KEY `nIndex10` (`NINDEX10`),
KEY `rel_display` (`REL_DISPLAY`),
KEY `App_Parent` (`META_OID`),
) ENGINE=InnoDB AUTO_INCREMENT=1245843 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPRESSED
Требуется всего 0,6 с для завершения. Я видел в других вопросах, что MATCH
пункт должен быть вложенным, но я не уверен, как его вложить в COUNT
заявление. Также при удалении meta_oid
предложение выполнено с использованием FULLTEXT
Индекс выполняется на 50% быстрее, чем второй запрос, поэтому, похоже, FULLTEXT
Я испытываю трудности при использовании его в сочетании с остальной частью запроса.meta_oid
индексируется, sIndex07
является varchar(1024)
а также база данных размером 4,5 Гб.
РЕДАКТИРОВАТЬ: причина, почему FULLTEXT
поиск был медленнее, потому что поисковый термин содержит дефис, поэтому в моем конкретном случае возвращается гораздо больший набор данных, чем LIKE
оператор. Поиск без дефиса использует FULLTEXT
и работает примерно в сто раз лучше, чем LIKE
Я присуду вознаграждение менее чем за 24 часа тому, кто может выполнить поиск с дефисами без перекомпиляции двоичных файлов mysql, что FULLTEXT
быстрее, что было первоначальной целью вопроса.
2 ответа
MySQL использует планировщик запросов, чтобы определить, как лучше всего разрешать запросы. Обычно для разрешения компонента WHERE используется только один индекс, который выбирается из списка возможных индексов, которые могут применяться. Список возможных индексов показан EXPLAIN под possible_keys
выбранный индекс обозначается key
, Чтобы сделать выбор, MySQL смотрит на ряд факторов, таких как уникальность индекса, чтобы попытаться определить, какой индекс сузит список возможных результатов лучше всего.
Как только он сузил список строк, которые совпадают в индексе. Будет Use Where
читать эти строки и проверять их на соответствие остальным условиям в предложении WHERE.
В этой операции есть много крайних случаев, и иногда MySQL может сделать плохой выбор. Планировщик запросов был значительно изменен в MySQL 5.1, и потребовалось несколько выпусков, прежде чем он снова стал хорошим.
Не имея ваших данных для анализа, трудно предположить, почему MySQL делает неправильный выбор. Хотя делаю:
SELECT SQL_NO_CACHE COUNT(*)
FROM e_entity
WHERE MATCH(sIndex07) AGAINST ("#UPR-1393#" IN NATURAL LANGUAGE MODE);
Сообщит вам, сколько строк MySQL читает из базы данных, используя полнотекстовый индекс. В вашем исходном запросе он затем должен проанализировать все эти строки с 'meta_oid=336799', чтобы определить окончательный счет.
SELECT SQL_NO_CACHE COUNT(*)
FROM e_entity
WHERE meta_oid=336799
Скажет вам, сколько фактических строк читает MySQL, используя App_Parent
индекс на META_OID
, Во втором запросе он должен проанализировать эти строки LIKE "%#UPR-1393#%"
Если последний запрос выдает намного меньшее число, чем первый, то он объясняет, почему он быстрее, когда App_Parent
вместо полнотекстового индекса.
MATCH(sIndex07)
нужен FULLTEXT
Индекс для эффективной работы. В противном случае это так же плохо (или хуже?), Чем LIKE '%string%'
,
Больше
Без FULLTEXT
это должно сделать LIKE
беги еще быстрее: INDEX(meta_oid=336799, sIndex07)