У меня есть таблица Assets
на движке InnoDB, определенная как:
CREATE TABLE Assets (
qid SMALLINT(5) NOT NULL,
sid BIGINT(20) NOT NULL AUTO_INCREMENT,
...
PRIMARY KEY (sid,qid),
KEY sid (sid)
);
Я запускаю следующий запрос:
SELECT COUNT(*) FROM Assets WHERE sid>10000;
На моей машине этот запрос занимает около 30 секунд с 2 миллионами записей в таблице. Теперь, если я изменяю запрос на использование индексов, результаты широко варьируются:
SELECT COUNT(*) FROM Assets USE INDEX(<index>) WHERE sid>10000;
-
NO INDEX
: нет явногоUSE INDEX
, т.е. первогоSELECT
запроса: 30 секунд -
KEY sid (sid)
: 1,5 секунды -
KEY cid (sid,qid)
: 1,5 секунды -
PRIMARY
: Я использовалUSE INDEX(PRIMARY)
в запросе.: 30 секунд
Итак, это мои вопросы:
-
Я думал, что запрос будет автоматически использовать первичный ключ в качестве индекса, основанный на этом. И все же между ними существует большая разница между
USE INDEX (cid)
иNO INDEX
. Какая разница? Кроме того, как я явно указываю первичный ключ как индекс? -
Если
NO INDEX
фактически не использует первичный ключ в качестве индекса, то что делаетUSE INDEX(PRIMARY)
, что заставляет его иметь такое же время работы, что иNO INDEX
? -
Есть ли разница между (
USE INDEX(sid)
"иUSE INDEX(cid)
) в запросе, который фильтрует толькоsid
?
Простите длинный пост, но я хотел позволить ему быть открытым для обсуждения.
Хорошо, вот что я выяснил до сих пор:
Прежде всего, мне сказали, что настройка ключа должна быть либо: PRIMARY KEY(qid,sid), KEY(sid)
, либо PRIMARY KEY(sid,qid), KEY(qid)
. Я не совсем понимаю разницу. Если кто-то это сделает, сообщите мне.
Во-вторых, KEY sid
(sid
) ссылается на гораздо меньше страниц индекса, чем на более крупный ключ, поэтому он имеет тенденцию быть быстрее. Что касается разницы между использованием PRIMARY KEY в качестве индекса и правильного KEY (даже если они используют одни и те же поля), мне сказали, что это примерно так:
Первичные ключи индексируют все данные таблицы с полями первичного ключа. Это означает, что ПЕРВИЧНЫЙ КЛЮЧ и данные хранятся вместе. Таким образом, запрос, использующий PRIMARY KEY, должен будет пройти через все данные таблицы, которые даже индексируются, будут падать на большие неупакованные таблицы.
С дискретными ключами число строк может быть одинаковым, но сканируется гораздо меньший индекс (состоящий из указанных полей), который попадает на меньшее количество блоков диска и, следовательно, работает намного быстрее. Я предполагаю, что это также является причиной разницы в использовании USE INDEX(cid)
и использовании первичного ключа в качестве индекса, оба из которых имеют одинаковые поля.