MySQL Multi Column Index не работает (как и ожидалось)?
-
10-10-2019 - |
Вопрос
У меня есть такой стол
CREATE TABLE IF NOT EXISTS `tbl_folder` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`owner_userid` int(11) NOT NULL,
`name` varchar(63) NOT NULL,
`description` text NOT NULL,
`visibility` tinyint(4) NOT NULL DEFAULT '2',
`num_items` int(11) NOT NULL DEFAULT '0',
`num_subscribers` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `owner_userid` (`owner_userid`),
KEY `vis_sub_item` (`visibility`,`num_subscribers`,`num_items`)
) ENGINE=InnoDB
Поскольку у меня есть индекс на видимости, num_subscribers и num_items, я ожидаю, что вместо этого необходимо рассмотреть только первые 15 строк, объясняющих 55856 строк. Есть идеи? Спасибо
EXPLAIN SELECT t.id, name, description, owner_userid, num_items, num_subscribers
FROM `tbl_folder` `t`
WHERE visibility =2
ORDER BY `t`.`num_subscribers` DESC , `t`.`num_items` DESC
LIMIT 15
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t ref vis_sub_item vis_sub_item 1 const 55856 Using where
Решение
Ваш 3 полевого индекса выглядит хорошо, а EXPLAIN
это многообещающе.
Хотя в нем написано «55856 рядов», это всего лишь оценивать предоставлено EXPLAIN
.
С key_len =1
, Вы знаете, что он использует первый байт вашего составного индекса в качестве равенства/ссылки.
Поскольку в вашем Extra
поле, вы знаете, что ORDER BY
/сортировка является обрабатывается индексом.
Если вы проверете свой handler_%
Сессионная статистика, у вас будет лучшее представление о том, сколько строк на самом деле читается.
Побочные мысли:
Поскольку вы знаете, что в конечном итоге вы нажидете на диск, чтобы забрать строки, если 99% ваших данных имеют visibility=2
(просто спекулируют), вы, вероятно, получите столь же хорошие/быстрые результаты с составным индексом только на num_subscribers
& num_items
. Анкет Или, возможно, так же хорошо/быстро, если у вас есть один индекс num_subscribers
, в зависимости от его кардинальности/уникальности.
Другие советы
Я не думаю, что EXPLAIN
смотрит на OFFSET
или же LIMIT
пункт. EXPLAIN
Предполагается указать, как будет выполнен запрос, какие ключи он использовал, как соединяются таблицы и т. Д. LIMIT
Пункт похож на модификатор Post Query ... теперь, когда мы знаем, что хотим, дайте им только первое. Таким образом, поле строк содержит количество возможных строк, которые существуют в запросе. Оттуда, OFFSET
а также LIMIT
Выберите конкретные, которые вы хотите.
Я полагаю, что если вы выполнили свой SELECT
без EXPLAIN
, вы получите количество записей, которые вы хотели.
Да, проблема в том, что ваш индекс неверен. Я имею в виду, что вы проиндексировали все 3 поля, а ваш выбранное запрос проверяет только один. В MySQL индексация 2 ряда отдельно отличается от индексации 3 строк вместе.
Пытаться
CREATE TABLE IF NOT EXISTS `tbl_folder` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`owner_userid` int(11) NOT NULL,
`name` varchar(63) NOT NULL,
`description` text NOT NULL,
`visibility` tinyint(4) NOT NULL DEFAULT '2',
`num_items` int(11) NOT NULL DEFAULT '0',
`num_subscribers` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `owner_userid` (`owner_userid`),
KEY `vis_index` (`visibility`),
KEY `vis_sub_item` (`num_subscribers`,`num_items`)
) ENGINE=InnoDB