Индекс 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)

Другие вопросы по тегам