Задавайте вопросы, мы ответим
Вы не зашли.
Есть сложные запросы, типа:
select distinct CONCAT_WS(" ", client.surname, client.name, client.middlename) as FULL_NAME from client, drivers where drivers.ID_DOGOVOR in ( select ID_DOGOVOR from dogovor where dogovor.ID_CAR in ( select ID_CAR from dogovor where dogovor.ID_CLIENT = :cln_id ) ) and (client.ID_CLIENT = drivers.ID_CLIENT) order by FULL_NAME;
Старый запрос:
select *, CONCAT_WS(" ", client.surname, client.name, client.middlename) as FULL_NAME from client where client.ID_CLIENT in (select ID_CLIENT from dogovor where dogovor.ID_DOGOVOR = :dog_id union select ID_CLIENT from drivers where drivers.ID_DOGOVOR = :dog_id union select car.ID_CLIENT from car, dogovor where dogovor.ID_DOGOVOR = :dog_id and dogovor.ID_CAR = car.ID_CAR ) order by SURNAME;
Выполняется запрос очень медленно.
Т.е., при смене вкладки в интерфейсе, программа затормаживает на 2-3 секунды.
Это очень заметно и сильно раздражает.
Возможно ли как-то ускорить выполнение запроса?
Улучшить запрос?
И каким образом?
Неактивен
Начните с переписывания запроса через JOIN. Подзапросы, скорее всего,
трактуются как зависимые (существующее ограничение MySQL), а потому
работают медленнее.
Неактивен
Хм... Чего-то не очень получается. А как "IN" переделать через JOIN?
Неактивен
select
distinct CONCAT_WS(" ", c.surname, c.name, c.middlename) as FULL_NAME
from client c
JOIN drivers d ON c.ID_CLIENT = d.ID_CLIENT
JOIN dogovor dg1 ON dg.ID_DOGOVOR = d.ID_DOGOVOR
JOIN dogovor dg2 ON dg1.ID_CAR = dg2.ID_CAR
WHERE dg2.ID_CLIENT = :cln_id
order by FULL_NAME;
Честно говоря, немного не понятна логика последнего вложения, кажется, что
достаточно будет одного вхождения таблицы договора. Но переписал ровно так,
как написано у Вас.
Неактивен
select ...
Спасибо огромное.
Вначале ругнулся на dg1 ON dg.ID_DOGOVOR, затем вылетел с SIGSEGV,
т.к. я про ID_CLIENT в результате забыл. Но сейчас работает.
Причём, за секунду или даже меньше.
Отлично. :-) Буду теперь разбираться как это работает.
Честно говоря, немного не понятна логика последнего вложения, кажется, что
достаточно будет одного вхождения таблицы договора. Но переписал ровно так,
как написано у Вас.
Логика такая:
Запрос на выборку лиц, имеющих отношения друг с другом.
Выбирает всех лиц, которые состоят в отношениях.
Т.е., например, собственник ТС и родственники собственника.
Или владелец ТС и водители, работающие на владельца.
1.) Выбрать ID ТС из всех договоров данного страхователя.
select ID_CAR from dogovor
where dogovor.ID_CLIENT = :cln_id
2.) Выбрать все договора, заключённые на данные ТС.
select ID_DOGOVOR from dogovor
where dogovor.ID_CAR in (1)
or dogovor.ID_CLIENT = :cln_id
3.) Выбрать всех водителей для списка договоров.
select * from client, drivers
where drivers.ID_DOGOVOR in (2)
and (client.ID_CLIENT = drivers.ID_CLIENT)
К примеру, есть ИП с несколькими авто. На них работают водители.
Водители включаются в договор страхования.
Если собственник покупает новое авто, то, очевидно, что он захочет добавить
тех же водителей в договор.
Собственно запрос выбирает всех водителей из всех договоров данного собственника.
После чего они подставляются в список, поскольку пользователь, очень вероятно, выберет кого-то из них.
Неактивен
Может, конечно, у меня есть избыточность в запросе... Ещё перепроверю.
Неактивен
А любые вложенные запросы теоретически возможно переписать через JOIN?
Отредактированно Артём Н. (07.03.2010 21:12:57)
Неактивен
Нет, не любые, но IN как раз хорошо переписываются.
Неактивен