Mysql Помогите новичку разобраться в индексах.

  • Автор темы Автор темы Cardee
  • Дата начала Дата начала

Cardee

Новичок
Если две таблицы:
Код:
mysql> SELECT * FROM `pages` WHERE `url` = "/url";
+--------+----------+----------+
| id     | url      | remove   |
+--------+----------+----------+
|      1 |     /url |        0 |
+--------+----------+----------+
|      2 |     /url |        1 |
+--------+----------+----------+
|      3 |     /url |        2 |
+--------+----------+----------+
С индексами:
  • PRIMARY на id;
  • уникальный индекс url на url и remove
  • индекс для частого запроса url_id_remove на все три столбца

Код:
mysql> SELECT * FROM `template` WHERE `id` IN (1, 2, 3);
+--------+--------+
| id     | tpl    |
+--------+--------+
|      1 |      1 |
+--------+--------+
|      2 |      1 |
+--------+--------+
|      3 |      1 |
+--------+--------+
С индексом PRIMARY на id и связью `template`.`id` = `pages`.`id`.

Частый запрос, в котором суть проблемы, для получение `pages`.`id` с минимальным значением `pages`.`remove`, у которого есть в наличие запись в `template`:
Код:
mysql> SELECT `pages`.`id` FROM `pages`, `template` WHERE `pages`.`url` = "/url" AND `template`.`id` = `pages`.`id` ORDER BY `pages`.`remove` ASC LIMIT 1;
В принципе всё работает быстро, но
Код:
mysql> EXPLAIN SELECT `pages`.`id` FROM `pages`, `template` WHERE `pages`.`url` = "/url" AND `template`.`id` = `pages`.`id` ORDER BY `pages`.`remove` ASC LIMIT 1;
+----+-------------+----------+--------+---------------------------+---------+---------+-------------+------+--------------------------+
| id | select_type | table    | type   | possible_keys             | key     | key_len | ref         | rows | Extra                    |
+----+-------------+----------+--------+---------------------------+---------+---------+-------------+------+--------------------------+
|  1 | SIMPLE      | pages    | ref    | PRIMARY,url,url_id_remove | url     | 767     | const       |    1 | Using where; Using index |
|  1 | SIMPLE      | template | eq_ref | PRIMARY                   | PRIMARY | 3       | db.pages.id |    1 | Using index              |
+----+-------------+----------+--------+---------------------------+---------+---------+-------------+------+--------------------------+
Объясните, пожалуйста, почему MySQL использует индекс url, а не url_id_remove? Почему при наличие индексов на все поля, участвующие в запросе, мне предлагается использовать индексы?
 
Сначала объясни, почему ты считаешь что БД должна использовать "на три столбца" и как она это будет делать?
 
Кстати, обрати внимание на длину ключа. И сколько он в итоге занимает места в памяти.
И поменяй кодировку таблицы на latin1
 
@Фанат, я только начинаю разбираться в этом.
Я думаю, что она определяет все используемые значения (это `id`, `url`, `remove`), определяет более подходящий ключ (url_id_remove) и использует его для поиска и сортировки.
Но похоже я много не знаю.
Спасибо за советы.

@Andreika, обязательно сегодня же посмотрю, чтобы не задавать больше глупых вопросов.
 
при наличии индексов на все поля, участвующие в запросе
А, понял теперь.
Виновата эта дебильная фраза, которую пишут составители пособий "25 идиотских фактов про пхп".

Разумеется, это абсолютно бессмысленная рекомендация. Индекс нужен по тем полям, которые влияют на выборку. А у тебя на нее влияют только url и remove.
поэтому и используется именно этот индекс.

А вот если поставить между url и remove абсолютно бессмысленный id, то оптимизатор может и не сообразить, что этот элемент индекса надо просто пропустить. И в любом случае между нормальным и кривым индексом выберет первый.
 
Последнее редактирование:
сначала задумайся почему поле из одной таблицы должно быть в индексе другой? я про `template`.`id`
 
Сверху