SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 15.12.2010 13:00:13

LazY
_cмельчак
MySQL Authorized Developer and DBA
Зарегистрирован: 02.04.2007
Сообщений: 849

Cоставной индекс: JOIN по его левой части и WHERE по последующим

Товарищи, столкнулся со следующей проблемой.

Есть составной ключ, пусть (id, blocked). Нужен JOIN с другой таблицей по id, но еще - условие WHERE blocked = 0.
Пишет, что используется только левая часть индекса (id, то есть).
Думал-думал, почему.. Пришел к выводу: оттого, что JOIN воспринимается как запрос вида IN(..).
Выходит, при JOIN можно использовать только левую часть индекса, а остальное отваливается, т.к. JOIN воспринимается как range.
Так получается?

Если да, то досадно т.к. от этой таблицы было нужно лишь количество записей (там группировка потом по другой таблице), просто с условием на blocked.
Получается, из-за этого условия придется для каждой записи на диск лазить, и ничего не поделаешь. Прямо не знаю, хоть индекс во временную таблицу в памяти загоняй..

Неактивен

 

#2 15.12.2010 13:22:29

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Cоставной индекс: JOIN по его левой части и WHERE по последующим

LazY написал:

Думал-думал, почему.. Пришел к выводу: оттого, что JOIN воспринимается как запрос вида IN(..).
Выходит, при JOIN можно использовать только левую часть индекса, а остальное отваливается, т.к. JOIN воспринимается как range.
Так получается?

Таблицы связаны по id на сколько я понимаю. Тогда при использовании id ты выдергиваешь запись из другой таблицы и помещаешь полученный результат (запись из первой таблицы + запись из второй) во временную таблицу. Понятно, что правая часть индекса из первой таблицы не используется при работе с временной таблицей.

Сделай индекс (blocked, id)

Неактивен

 

#3 15.12.2010 19:13:36

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Cоставной индекс: JOIN по его левой части и WHERE по последующим

От себя добавлю, что это, кажется, тот случай, когда условие надо засунуть
в ON, т.е. ON (this.id = that.id AND that.blocked = 0). Подозреваю, что в этом
случае индекс будет использоваться целиком.

Неактивен

 

#4 18.12.2010 19:35:44

LazY
_cмельчак
MySQL Authorized Developer and DBA
Зарегистрирован: 02.04.2007
Сообщений: 849

Re: Cоставной индекс: JOIN по его левой части и WHERE по последующим

vasya написал:

при использовании id ты выдергиваешь запись из другой таблицы и помещаешь полученный результат (запись из первой таблицы + запись из второй) во временную таблицу. Понятно, что правая часть индекса из первой таблицы не используется при работе с временной таблицей.

Так мне во временной таблице правая часть и не нужна. Но я надеялся, что перед созданием временной таблицы будет учтено условие WHERE (а я верю, что это перед созданием временной таблицы делается), которое сможет посмотреть в правую часть индекса и на диск не полезет. А получается по-другому.
Индекс (blocked, id) тут вряд ли поможет, т.к. JOIN-то по id - наверняка MySQL не сможет для JOIN использовать правую часть индекса.

paulus написал:

От себя добавлю, что это, кажется, тот случай, когда условие надо засунуть
в ON, т.е. ON (this.id = that.id AND that.blocked = 0).

Мысль интересная, попробую... (тогда получится, что MySQL один и тот же индекс может использовать только для одной операции; т.е. если им пользуется JOIN, то WHERE в него уже смотреть не будет)

Неактивен

 

#5 20.12.2010 10:54:12

LazY
_cмельчак
MySQL Authorized Developer and DBA
Зарегистрирован: 02.04.2007
Сообщений: 849

Re: Cоставной индекс: JOIN по его левой части и WHERE по последующим

paulus написал:

это, кажется, тот случай, когда условие надо засунуть
в ON, т.е. ON (this.id = that.id AND that.blocked = 0).

Так и есть! Спасибо, получилось.

(Примечание: скобки после ON не нужны)

Неактивен

 

#6 04.01.2011 22:50:59

Shopen
Гуру
Откуда: Москва
Зарегистрирован: 22.10.2007
Сообщений: 362

Re: Cоставной индекс: JOIN по его левой части и WHERE по последующим

В недрах памяти сидит, что вроде как все ON (условие) преобразуются во WHERE (условие) оптимизатором. Из данного случая получается, что это не совсем так. Я как то натыкался на аналогичный момент. Кто-нибудь может популярно объяснить в чем тонкость?

С Новым Годом, кстати, коллеги smile
Успешной работы smile

Неактивен

 

#7 05.01.2011 14:03:04

rgbeast
Администратор
MySQL Authorized Developer and DBA
Откуда: Москва
Зарегистрирован: 21.01.2007
Сообщений: 3880

Re: Cоставной индекс: JOIN по его левой части и WHERE по последующим

Я бы думал наоборот, что условие WHERE преобразуется в JOIN. Например, такое бывает, если JOIN без условия, а соответствующее условие есть в WHERE. Однако по своей сути JOIN и WHERE две совершенно разные операции и если у каждой из них есть условие, оптимизатор может и ничего не переносить. Это общее свойство оптимизатора MySQL, что он ничего не делает, кроме нескольких заранее известных ему частных случаев.

C Новым годом!

Неактивен

 

#8 05.01.2011 16:06:38

Shopen
Гуру
Откуда: Москва
Зарегистрирован: 22.10.2007
Сообщений: 362

Re: Cоставной индекс: JOIN по его левой части и WHERE по последующим

Пошло это, по всей видимости вот откуда. Вот страница из доки (версия значения не имеет) - http://dev.mysql.com/doc/refman/5.5/en/ … ation.html
п.3 -

The LEFT JOIN condition is used to decide how to retrieve rows from table B. (In other words, any condition in the WHERE clause is not used.)

Вот ее перевод на mysql.ru (далее растиражированный по всем интернетам) - http://www.mysql.ru/docs/man/LEFT_JOIN_ … ation.html

п.3 -

Все условия LEFT JOIN перемещаются в предложение WHERE.

хе-хе smile

Неактивен

 

#9 06.01.2011 17:20:07

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Cоставной индекс: JOIN по его левой части и WHERE по последующим

Да, я знал, что надо всегда читать оригинал smile

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson