Mysql запрос оптимизации с использованием индексов - PullRequest
4 голосов
/ 14 июля 2011

Моя схема БД состоит из следующих двух таблиц:

CREATE TABLE `categories` (
  `id` bigint(20) NOT NULL auto_increment,
  `title` varchar(128) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

и

CREATE TABLE `articles` (
  `id` bigint(20) NOT NULL auto_increment,
  `title` varchar(512) NOT NULL,
  `body` longtext,
  `state` varchar(7) NOT NULL,
  `type` varchar(6) NOT NULL,
  `category` bigint(20) default NULL,
  `publishedAt` datetime default NULL,
  PRIMARY KEY  (`id`),
  KEY `FK_category_to_article_category` (`category`),
  CONSTRAINT `FK_category_to_article_category` FOREIGN KEY (`category`) REFERENCES `categories` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Для таблицы статей в столбце state есть значения, такие как «ОПУБЛИКОВАНО» или «НЕУДАЧЕНО»и столбец type имеет значения, такие как "NEWS", "GOSSIP" и "OPINION".

Мое приложение выполняет много запросов, подобных этому:

select * from articles where state="PUBLISHED" and type in ("NEWS","GOSSIP") 
and category in (4) and publishedAt<=now() order by publishedAt desc;

У меня ~ 10K статейи я пытаюсь определить, работает ли вышеуказанный запрос лучше с внешним ключом по умолчанию для категории, или я должен вместо этого использовать индекс из нескольких столбцов.

Без индекса (с использованием «расширенного объяснения»):

+----+-------------+-------+------+---------------------------------+---------------------------------+---------+-------+------+-----------------------------+
| id | select_type | table | type | possible_keys                   | key                             | key_len | ref   | rows | Extra                       |
+----+-------------+-------+------+---------------------------------+---------------------------------+---------+-------+------+-----------------------------+
|  1 | SIMPLE      | this_ | ref  | FK_category_to_article_category | FK_category_to_article_category | 9       | const |  630 | Using where; Using filesort |
+----+-------------+-------+------+---------------------------------+---------------------------------+---------+-------+------+-----------------------------+

Если я создаю многостолбцовый индекс и повторяю объяснение (форсирование определенного индекса):

create index I_s_t_c_p on articles (state, type, category, publishedAt);


+----+-------------+-------+-------+---------------+-----------+---------+------+------+------------------------------------------+
| id | select_type | table | type  | possible_keys | key       | key_len | ref  | rows | Extra                                    |
+----+-------------+-------+-------+---------------+-----------+---------+------+------+------------------------------------------+
|  1 | SIMPLE      | this_ | range | I_s_t_c_p     | I_s_t_c_p | 61      | NULL | 1216 | Using where; Using index; Using filesort |
+----+-------------+-------+-------+---------------+-----------+---------+------+------+------------------------------------------+

Количество строк, которые фактически возвращает запрос, равно 630. Мне кажется, что многостолбцовый индекс должен работать лучше, чем FK, поскольку используются все индексированные столбцы, но факт использования ~ 1200 строк при использовании индексасмущает меняЯ знаю, что эти цифры - только оценки, но разница между этими двумя ключами довольно большая;с объединенным индексом мы имеем двойное количество проверенных строк.

Итак, у меня следующие вопросы:

  1. Почему так много строк проверяется с индексом из нескольких столбцов?
  2. Поскольку с помощью FK у нас есть тип соединения«ref» и используя объединенный индекс, мы имеем тип соединения «range», означает ли это, что запрос, использующий FK, лучше / быстрее, чем другой?
  3. Должен ли я использовать оценку для числастрок, рассматриваемых в качестве критерия для определения, является ли индекс хорошим / оптимальным?
  4. В этом случае использования многостолбцовый индекс лучше, чем FK?На каком основании я должен принять решение?

Некоторая дополнительная информация:

  • Не форсируя индекс запроса, оптимизатор выбрал FK.Когда я выполнил analyze table для статей, вместо этого был выбран многостолбцовый индекс.
  • Я использую MySql 5.0.15
  • Индекс

+----------+------------+---------------------------------+--------------+-------------+-------------+------------+
| Table    | Non_unique | Key_name                        | Seq_in_index | Column_name | Cardinality | Index_type |
+----------+------------+---------------------------------+--------------+-------------+-------------+------------+
| articles |          0 | PRIMARY                         |            1 | id          |       12561 | BTREE      |
| articles |          1 | FK_category_to_article_category |            1 | category    |          37 | BTREE      |
| articles |          1 | I_s_t_c_p                       |            1 | state       |           8 | BTREE      |
| articles |          1 | I_s_t_c_p                       |            2 | type        |          32 | BTREE      |
| articles |          1 | I_s_t_c_p                       |            3 | category    |         163 | BTREE      |
| articles |          1 | I_s_t_c_p                       |            4 | publishedAt |       12561 | BTREE      |
+----------+------------+---------------------------------+--------------+-------------+-------------+------------+

Заранее спасибо.

1 Ответ

2 голосов
/ 14 июля 2011

Как вы можете видеть, индекс на publishedAt имеет ту же мощность, что и PK. Это не очень помогает. Я бы попытался создать составной индекс со столбцами в таком порядке (category,type,state). Таким образом, первая часть индекса является наиболее избирательной.

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