У меня есть таблица 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) и использовании первичного ключа в качестве индекса, оба из которых имеют одинаковые поля.