SQLinfo.ru - Все о MySQL

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

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

Вы не зашли.

#1 07.03.2010 11:16:57

Артём Н.
Активист
Зарегистрирован: 03.11.2009
Сообщений: 156

Как ускорить выполнение запроса?

Есть сложные запросы, типа:

Код:

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 секунды.
Это очень заметно и сильно раздражает.
Возможно ли как-то ускорить выполнение запроса?
Улучшить запрос?
И каким образом?


"И ни птица, ни ива слезы не прольет,
Если сгинет с земли человеческий род.
И весна, и весна встретит новый рассвет,
Не заметив, что нас уже нет..."

Неактивен

 

#2 07.03.2010 18:52:21

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

Re: Как ускорить выполнение запроса?

Начните с переписывания запроса через JOIN. Подзапросы, скорее всего,
трактуются как зависимые (существующее ограничение MySQL), а потому
работают медленнее.

Неактивен

 

#3 07.03.2010 20:20:16

Артём Н.
Активист
Зарегистрирован: 03.11.2009
Сообщений: 156

Re: Как ускорить выполнение запроса?

Хм... Чего-то не очень получается. А как "IN" переделать через JOIN?


"И ни птица, ни ива слезы не прольет,
Если сгинет с земли человеческий род.
И весна, и весна встретит новый рассвет,
Не заметив, что нас уже нет..."

Неактивен

 

#4 07.03.2010 20:39:16

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

Re: Как ускорить выполнение запроса?

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;

Честно говоря, немного не понятна логика последнего вложения, кажется, что
достаточно будет одного вхождения таблицы договора. Но переписал ровно так,
как написано у Вас.

Неактивен

 

#5 07.03.2010 21:08:42

Артём Н.
Активист
Зарегистрирован: 03.11.2009
Сообщений: 156

Re: Как ускорить выполнение запроса?

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)

К примеру, есть ИП с несколькими авто. На них работают водители.
Водители включаются в договор страхования.
Если собственник покупает новое авто, то, очевидно, что он захочет добавить
тех же водителей в договор.
Собственно запрос выбирает всех водителей из всех договоров данного собственника.
После чего они подставляются в список, поскольку пользователь, очень вероятно, выберет кого-то из них.


"И ни птица, ни ива слезы не прольет,
Если сгинет с земли человеческий род.
И весна, и весна встретит новый рассвет,
Не заметив, что нас уже нет..."

Неактивен

 

#6 07.03.2010 21:10:00

Артём Н.
Активист
Зарегистрирован: 03.11.2009
Сообщений: 156

Re: Как ускорить выполнение запроса?

Может, конечно, у меня есть избыточность в запросе... Ещё перепроверю.


"И ни птица, ни ива слезы не прольет,
Если сгинет с земли человеческий род.
И весна, и весна встретит новый рассвет,
Не заметив, что нас уже нет..."

Неактивен

 

#7 07.03.2010 21:12:39

Артём Н.
Активист
Зарегистрирован: 03.11.2009
Сообщений: 156

Re: Как ускорить выполнение запроса?

А любые вложенные запросы теоретически возможно переписать через JOIN?

Отредактированно Артём Н. (07.03.2010 21:12:57)


"И ни птица, ни ива слезы не прольет,
Если сгинет с земли человеческий род.
И весна, и весна встретит новый рассвет,
Не заметив, что нас уже нет..."

Неактивен

 

#8 09.03.2010 13:38:32

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

Re: Как ускорить выполнение запроса?

Нет, не любые, но IN как раз хорошо переписываются.

Неактивен

 

Board footer

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