многостолбцовый индекс mysql не работает (как и ожидалось)? - PullRequest
5 голосов
/ 08 декабря 2010

У меня есть такая таблица

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_subscribeers и num_items, я ожидаю, что нужно просматривать только первые 15 строк, вместо этого EXPLAIN говорит 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 ]

2 голосов
/ 09 декабря 2010

Ваш индекс из 3 полей выглядит хорошо, а EXPLAIN обещает.

Несмотря на то, что он говорит "55856 строк", это всего лишь оценка , предоставленная EXPLAIN.

Поскольку key_len =1, вы знаете, что он использует первый байт вашего составного индекса в качестве равенства / ссылки.

Поскольку в вашем поле Extra нет файловой сортировки, вы знаете, что ORDER BY / sorting - это , обрабатываемый индексом.

Если вы проверите свою handler_% статистику сеанса, у вас будет более точное представление о том, сколько строк фактически читается.

Побочные мысли:

Поскольку вы знаете, что в конечном итоге вы попадете на диск, чтобы получить свои строки, если 99% ваших данных имеют visibility=2 (просто предположения), вы, вероятно, получите столь же хорошие / быстрые результаты с составным индексом, простона num_subscribers & num_items.Или, возможно, как хороший / быстрый, если у вас есть один индекс на num_subscribers, в зависимости от его кардинальности / уникальности.

0 голосов
/ 08 декабря 2010

да, проблема в том, что ваш индекс неверен.Я имею в виду, что вы проиндексировали все 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
0 голосов
/ 08 декабря 2010

Я не думаю, что EXPLAIN смотрит на предложение OFFSET или LIMIT. EXPLAIN должен указывать, как будет выполняться запрос, какие ключи он использовал, как объединяются таблицы и т. Д. Предложение LIMIT похоже на модификатор пост-запроса ... теперь, когда мы знаем, чего хотим, только дай им первое так много. Таким образом, поле строк содержит количество возможных строк, которые существуют в запросе. Оттуда OFFSET и LIMIT выберут те, которые вам нужны.

Я полагаю, что если бы вы выполнили SELECT без EXPLAIN, вы бы получили желаемое количество записей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...