Моя схема БД состоит из следующих двух таблиц:
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 строк при использовании индексасмущает меняЯ знаю, что эти цифры - только оценки, но разница между этими двумя ключами довольно большая;с объединенным индексом мы имеем двойное количество проверенных строк.
Итак, у меня следующие вопросы:
- Почему так много строк проверяется с индексом из нескольких столбцов?
- Поскольку с помощью FK у нас есть тип соединения«ref» и используя объединенный индекс, мы имеем тип соединения «range», означает ли это, что запрос, использующий FK, лучше / быстрее, чем другой?
- Должен ли я использовать оценку для числастрок, рассматриваемых в качестве критерия для определения, является ли индекс хорошим / оптимальным?
- В этом случае использования многостолбцовый индекс лучше, чем 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 |
+----------+------------+---------------------------------+--------------+-------------+-------------+------------+
Заранее спасибо.