Модераторы: skyboy
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Индексирование select where in (select) 
:(
    Опции темы
setnull
Дата 22.2.2010, 00:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 417
Регистрация: 3.7.2007

Репутация: нет
Всего: 1



Все здравствуйте!

Есть батарея вложенных запросов типа
Код

select id1
 from table1 where field1 in (
       select id 2
       from  table2 where field2 in(
            select id3 
            from table3 where field3 in(
              .........
            )
       )
)


Все поля соответствующие поля проиндексированЫ.
Но в плане пишется (и собственно сам запрос выполняется медленно), что самый внешний запрос не индексирован, в отличии от всех подзапросов.
Пишет, что внешней таблицы возможные и используемые ключи НУЛЛ, и говорит, что используется (понимаю для сканирования) where.
Когда у вложенных там пишутся первичные ключи и говорит, что используется индекс
И, что интересно, если исполнять самостоятельно фрагменты подзапросов  (на любой стадии вложенности), то для них сохраняется та же тенденция: внешний (и только внешний) запрос не индексируется!
Не помогает также и явное указание к использованию соответствующего индекса use undex (my_index)!

Почему так происходит?
Что делать?

Спасибо!!!
PM MAIL   Вверх
setnull
Дата 22.2.2010, 02:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 417
Регистрация: 3.7.2007

Репутация: нет
Всего: 1



прошу прощения.
c using where ситуация чуть другая...;

в общем
user posted image
вот количество строк в результирующей выборке, к примеру 4963, тогда как в rows, обработанных для table1, показывает 1951194.
И еще что странно, что для остальных таблиц rows = 1. Тогда как действительно средние два подзапроса возвращают явно многострочные наборы данных.
??????????
Но, все же, главный вопрос, почему внешний запрос не использует индексы?


PM MAIL   Вверх
setnull
Дата 22.2.2010, 02:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 417
Регистрация: 3.7.2007

Репутация: нет
Всего: 1



Странно!
Если исходный запрос обернуть дополнительно следующим образом

Код

select id1
from table1 where id1 in(
    исходный запрос
)


то пишет, что ключ и индекс используются 
user posted image
НО!!!!!!
1) запрос выполняется еще медленнее и обрабатываемое количество записей все равно остается 1951194 (и, что тоже странно, <> общему количеству строк в table1 1969719)
2)  не понятна логика, ведь оба указанных поля одинаково проиндексированы. С той только разницей, что id - первичный ключ.

жду Вашего совета!!!
Спасибо!!!

Это сообщение отредактировал(а) setnull - 22.2.2010, 02:39
PM MAIL   Вверх
skyboy
Дата 22.2.2010, 09:33 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


Профиль
Группа: Модератор
Сообщений: 9820
Регистрация: 18.5.2006
Где: Днепропетровск

Репутация: 41
Всего: 260



какой-то стремный запрос. почему бы не использовать join?
PM MAIL   Вверх
sTa1kEr
Дата 22.2.2010, 13:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


9/10 программиста
***


Профиль
Группа: Завсегдатай
Сообщений: 1553
Регистрация: 21.2.2007

Репутация: 7
Всего: 146



Код

SELECT id1
FROM table1 AS t1
    JOIN table2 AS t2 ON t1.field1 = t2.id2
    JOIN table3 AS t3 ON t2.field2 = t3.id3
    JOIN table4 AS t4 ON t3.field3 = t4.id4

PM MAIL   Вверх
setnull
Дата 23.2.2010, 01:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 417
Регистрация: 3.7.2007

Репутация: нет
Всего: 1



Контекст:
 InnoDB базы быстро и беспорядочно разростаются - отказываемся от InnoDB, теряем возможность использовать внешние ключи
 Хостер не дает использовать триггеры
Для поддержания целостности БД, удаления записей производятся процедурами, получающими на входе условие, фильтрующее удаляемые из текущей таблицы записи (к примеру 
Код

' where my_field = ''my_value'''
). Процедуры исполняют подготавливаемый запрос на удаление 
Код

delete from ... + <условие>
, предварительно вызывая соответствующие процедуры удаления зависимых (дочерних по "внешнему отношению") таблиц с условиями 
Код

where foreign_key_field in (select id from actual_table + <условие>)
.
1) Буду очнь признателен, если кто поможет в решении именно этой задачи (отдельное спасибо за перестройку представленной мной конструкции в конструкцию с объединениями smile ) но при этом:
2) Даже если эту всю логику запихнуть в соединения и т.д., то в любом случае в итоге мы придем опять-таки к тому же 
Код

delete where id in (то, что удастся намудрить)
, т.к. не очень мне нравится вручную построчно удалять из таблицы по списку id  из курсора
Код

select id from то, что удастся намудрить

Т.к. если логика удаления чуть сложнее, чем 
Код

delete from my_table where create_date < today()-7

и завязана на данных из других таблиц, то без where filed in (select) никак не обойтись(или в МэйСКЛ есть что-то подобное удалениям из соединений МССКЛ?), а он все так же не использует индексы!!!!!!!!!! И больше того, в подзапросе такого delete не допускается использование исходной таблицы, из которой производится удаление smile)))))))))))
3) Я конечно буду очень рад, если здесь мне помогут с моей практической задачей, но все же, в любом случае, структура where in (select), как никак, часть стандарта? Ее применение не ограничивается исключительно данной здачей. И мой целевой вопрос был ориентирован на то, чтоб узнать, почему она работает именно так, и чтоб разобраться, как корректно ее использовать с расчетом на эффективное выполнение.
Спасибо!!!
PM MAIL   Вверх
sTa1kEr
Дата 23.2.2010, 12:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


9/10 программиста
***


Профиль
Группа: Завсегдатай
Сообщений: 1553
Регистрация: 21.2.2007

Репутация: 7
Всего: 146



Код

DELETE t1
FROM table1 AS t1
    JOIN table2 AS t2 ON t1.field1 = t2.id2
    JOIN table3 AS t3 ON t2.field2 = t3.id3
    JOIN table4 AS t4 ON t3.field3 = t4.id4
WHERE t4.field4 = 'condition'


Добавлено через 5 минут и 55 секунд
Цитата(setnull @  23.2.2010,  02:43 Найти цитируемый пост)
3) Я конечно буду очень рад, если здесь мне помогут с моей практической задачей, но все же, в любом случае, структура where in (select), как никак, часть стандарта? Ее применение не ограничивается исключительно данной здачей. И мой целевой вопрос был ориентирован на то, чтоб узнать, почему она работает именно так, и чтоб разобраться, как корректно ее использовать с расчетом на эффективное выполнение.

Приведите конкретную задачу где без нее не обойтись. А вообще вложенных подзапросов стоит избегать.
PM MAIL   Вверх
setnull
Дата 23.2.2010, 12:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 417
Регистрация: 3.7.2007

Репутация: нет
Всего: 1



Благодарю!!!!!!!!
столкнусь - обязательно напишу   smile

Более того!!!!!!!!
можно
Код

DELETE t1, t2
FROM table1 AS t1
    JOIN table2 AS t2 ON t1.field1 = t2.id2
    JOIN table3 AS t3 ON t2.field2 = t3.id3
    JOIN table4 AS t4 ON t3.field3 = t4.id4
WHERE t4.field4 = 'condition'


Это сообщение отредактировал(а) setnull - 23.2.2010, 12:47
PM MAIL   Вверх
setnull
Дата 27.2.2010, 10:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 417
Регистрация: 3.7.2007

Репутация: нет
Всего: 1



вот хороший пример.
Он надуманный (точнее выдуманный), но отражает нюанс
Есть 
Собственники
Сети магазинов
Магазины

Нужно выбрать Собственников по критерию определяемому магазином (пусть по географическому расположению).
Так можно либо сделать запрос Собственников where exists(соотв магазины), либо поприсоединять все и сгруппировать по полям Собственника интересующей информации.

А если еще и нужно навыбирать информацию о Собственнике, не касающуюся деятельности магазинов (Историю местопроживания в период превышения индекса махинацийи в туристическом бизнесе определенного порога и Движение денежных счетов, открытых в вылюте, показавшей максимальный тренд за прошлый месяц), то, думаю, вообще как тут соединять все в одну яму, множить строки громадных выборок комбинациями, а потом там пытаться что-то выгрести и проанализировать?
Вот если даже и заставить себя написать такой запрос с соединениями (и такое получится), то как у сервера получится справится с ним эффективнее чем с подзапросами, если он даже не пользуется индексами при элементарном where  in (select)?
PM MAIL   Вверх
setnull
Дата 27.2.2010, 10:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 417
Регистрация: 3.7.2007

Репутация: нет
Всего: 1



а еще
вот это тоже считается подзапросом и тоже не стоит использовать?
Код

select
*
from sth1
left join sth2
left join (
select sth3 inner join sth4
)

PM MAIL   Вверх
skyboy
Дата 27.2.2010, 13:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


Профиль
Группа: Модератор
Сообщений: 9820
Регистрация: 18.5.2006
Где: Днепропетровск

Репутация: 41
Всего: 260



Цитата(setnull @  27.2.2010,  09:43 Найти цитируемый пост)
вот это тоже считается подзапросом и тоже не стоит использовать?

в данной форме - как cross join четырем таблиц - его использовать невозможно. точнее, не могу представить ситуации, когда без декартового произведения четырех таблиц нельзя было бы обойтись.
может, вместо придумывания синтетичиских ситуаций, в которых "можно было бы использовать подзапрос"(если тебе так хочется, используй подзапросы везде; запретить тебе никто не может), привел бы реальную задачу, в которой ты не можешь представить, как использовать join?
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | MySQL | Следующая тема »


 




[ Время генерации скрипта: 0.0545 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.