TroL929
@TroL929
веб-программист

Как оптимизировать такой sql запрос?

SELECT a.*, 
c.family, c.imya, c.otchestvo, c.phone,
u.`name` AS nameUslug, meet.id AS meet,  meet.dateMeet, meet.dateWasMeet, calls.id AS calls, calls.dateCall, 
office.demoName AS officeName, cl.id AS complaint, 
us1.name AS userCreated_name,
us2.name AS userDogovor_name,
us3.name AS userComplete_name
FROM ankets a 
LEFT JOIN clients c ON c.id = a.`client`
LEFT JOIN uslugi u ON u.id = a.usluga
LEFT JOIN meet  ON meet.id = a.meet
LEFT JOIN calls  ON calls.id = a.`call`
LEFT JOIN office  ON office.id = c.office

LEFT JOIN users us1 ON us1.id = a.userCreated
LEFT JOIN users us2 ON us2.id = a.userDogovor
LEFT JOIN users us3 ON us3.id = a.userComplete

LEFT JOIN anket_user au  ON au.anketa = a.id
LEFT JOIN anket_group ag  ON ag.anketa = a.id
LEFT JOIN complaint cl  ON cl.anketa = a.id AND cl.`status` = '0'
WHERE a.`status` = '1' AND a.`delete` = '0' 
AND ((au.`user` = '1' AND au.`status` = '1') OR (ag.`group` = '2' AND ag.`status` = '1' AND (c.`office` = '1' OR c.`office` = '3' OR c.`office` = '0')) )


Есть такой большой код, как можно его оптимизировать и ускорить?

Вот скрип детализации запроса gyazo.com/86c4737debbf4c10b203c3f612d185ad
  • Вопрос задан
  • 496 просмотров
Решения вопроса 1
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
Выдайте этот запрос в консоли, добавив перед ним команду EXPLAIN. Получите план запроса, в нём смотрите где и какие индексы используются, где их надо добавить.
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
@nozzy
Symfony, Laravel, SQL
Не понял что там с users,
может убрать два join-а :
LEFT JOIN users us1 ON us1.id = a.userCreated
LEFT JOIN users us2 ON us2.id = a.userDogovor
LEFT JOIN users us3 ON us3.id = a.userComplete

=>

LEFT JOIN users us1 ON us1.id IN (a.userCreated, a.userDogovor, a.userComplete)
Ответ написан
@Wol_fi
php, js, mysql, highload
MYSQL джоинит таблицы через внутренние циклы. Такое количество джоинов - убийственно. Может вам стоит подумать о денормализации данных?
Ответ написан
inside22
@inside22
Вячеслав Беляев если вы работаете на PHP, создайте один класс Questionary методом getQuestionary()
и дальше используйте примено так, передавайте критерии и получайте ответ:

$questionaryObj= Questionary->getQuestionary(array(
    'status' => 1,
    'delete' => 0,
));

Это вместо первого запроса к таблице ankets.
Далее крутим полученные данные и получаем оставшиеся данные:
foreach($questionaryObj as $questionary) {

    $clientObj= Client->getClient(array('cliendId' => $questionary->cliendId));
    $serviceObj= Service->getService(array('serviceId' => $questionary->serviceId));
    $meetObj= Meet->getMeet(array('meetId' => $questionary->meetId));
    $userCreatedName = User->getUser(array('userCreated' => $questionary->userId));
    $userDogovorName  = User->getUser(array('userDogovor' => $questionary->userDogovor));
    $userCompleteName  = User->getUser(array('userComplete' => $questionary->userComplete));

    $responceArr = array(
        'name' => $clientObj->name,
        'lastname' => $clientObj->lastname,
        'patronymic' => $clientObj->patronymic,
        'phone' => $clientObj->phone,
        'serviceName' => $serviceObj->name,
        'meet' => $meetObj->meet,
        'wasMeet' => $meetObj->wasMeet,
        'dateMeet' => $meetObj->dateMeet,
        'serviceName' => $serviceObj->name
    );
}


И в итоге собираете массив с нужными вами данными.
Плюс этого способа в том, что выполняются мелкие и простые SQL-запросы.
Большие и сложный запросы сложно поддераживать.

Помими этого, если вам завтра прийдется менять какую-то таблицу или таблицы, вам не прийдется переписывать все ваши боооольшущие запросы, вам надо будет переписать только один запрос в одном методе...
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы