Выборка с joinWith тормозит запрос

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
quasar
Сообщения: 109
Зарегистрирован: 2014.10.22, 09:27

Выборка с joinWith тормозит запрос

Сообщение quasar »

Вообщем такая история - есть три таблицы (категории, компании, филиалы) Между собой они увязаны, индексы и ключи проставлены. Выборка когда джойню категории к компаниям идет нормально. Как только приджойню филиалы выборка идет очень долго, до 5 сек.
Вот пример кода запроса:

Код: Выделить всё

$query = \app\models\Companies::find()

                ->with(['category', 'citys', 'category.parentCategory'])
                ->joinWith(['relsubcompany', 'filials'])
                ->where(['relations_subcategory_company.subcategory_id'=>$podcategory->id,])
                
                ->andWhere(['companies.active'=>1])
                ->orderBy('companies.balls DESC');
  $query->orFilterWhere(['=', 'filials.area_id', $area->id]);
                 
В итоге генерится запрос

Код: Выделить всё

SELECT `companies`.* FROM `companies` LEFT JOIN `relations_subcategory_company` ON `companies`.`id` = `relations_subcategory_company`.`company_id` LEFT JOIN `filials` ON `companies`.`id` = `filials`.`id_company` WHERE (((`relations_subcategory_company`.`subcategory_id`='760') AND (`companies`.`active`=1)) AND (`companies`.`area_id` = 15)) OR (`filials`.`area_id` = 15) ORDER BY `companies`.`balls` DESC 
Без филиалов выстреливает как пуля.

Второй вопрос, я так понимаю что при joinWith вытягивается только главная таблица по приджойненой идет только поиск. Как вытянуть поля и из приджойненой таблицы и как потом их выводить.
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: Выборка с joinWith тормозит запрос

Сообщение samdark »

EXPLAIN покажите.
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: Выборка с joinWith тормозит запрос

Сообщение samdark »

Поля втягиваются отдельным запросом типа where ID in (1,2,3,...)
quasar
Сообщения: 109
Зарегистрирован: 2014.10.22, 09:27

Re: Выборка с joinWith тормозит запрос

Сообщение quasar »

Sam Dark писал(а):EXPLAIN покажите.
Изображение
quasar
Сообщения: 109
Зарегистрирован: 2014.10.22, 09:27

Re: Выборка с joinWith тормозит запрос

Сообщение quasar »

Sam Dark писал(а):Поля втягиваются отдельным запросом типа where ID in (1,2,3,...)
Я конечно не особо гуру в вопросе таких сложных выборок, то что понял то и сочинил))) Чего тормозит вообще не пойму...
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Выборка с joinWith тормозит запрос

Сообщение ElisDN »

На active и area_id индексы сделайте.
quasar
Сообщения: 109
Зарегистрирован: 2014.10.22, 09:27

Re: Выборка с joinWith тормозит запрос

Сообщение quasar »

ElisDN писал(а):На active и area_id индексы сделайте.
В таблице компаний на active индекс есть, area_id тоже вроди есть индекс. Может проблема в том что в таблице компаний и таблице филиалов название полей совпадают по которым идет поиск?
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: Выборка с joinWith тормозит запрос

Сообщение samdark »

limit добавьте. Похоже, у вас выбирается 166666 компаний за один раз...
quasar
Сообщения: 109
Зарегистрирован: 2014.10.22, 09:27

Re: Выборка с joinWith тормозит запрос

Сообщение quasar »

Объясню задачу которую пытаюсь решить. Нужно вывести все компании которые есть в данном городе и те компании которые имеют филиалы в этом городе. Тоесть поиск ведется и по area_id компании, так и area_id филиала если или там или там совпадение компанию отбираем. Потом весь результат надо отсортировать по полю balls. Вроди не сложная задача но гдето туплю.
quasar
Сообщения: 109
Зарегистрирован: 2014.10.22, 09:27

Re: Выборка с joinWith тормозит запрос

Сообщение quasar »

Sam Dark писал(а):limit добавьте. Похоже, у вас выбирается 166666 компаний за один раз...
Лимит есть

Код: Выделить всё

 // подключаем класс Pagination, выводим по 10 пунктов на страницу
        $pages = new Pagination(['totalCount' => $vsego, 'pageSize' => 10]);
        // приводим параметры в ссылке к ЧПУ
        $pages->pageSizeParam = false;
        $company = $query->offset($pages->offset)
            ->limit($pages->limit)
            ->all(); 
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: Выборка с joinWith тормозит запрос

Сообщение samdark »

Вы выше писали, что генерится без LIMIT вроде.
quasar
Сообщения: 109
Зарегистрирован: 2014.10.22, 09:27

Re: Выборка с joinWith тормозит запрос

Сообщение quasar »

Выше то просто формирования самого запроса, потом он дальше бьется на лимиты пагинатором. Хотя да, чтото в запросе я не вижу лимит, гдето потерялся...
quasar
Сообщения: 109
Зарегистрирован: 2014.10.22, 09:27

Re: Выборка с joinWith тормозит запрос

Сообщение quasar »

Приведу весь код

Код: Выделить всё

 $query = \app\models\Companies::find()
                ->with(['category', 'citys', 'category.parentCategory'])
                ->joinWith(['relsubcompany', 'filials'])
                ->where(['relations_subcategory_company.subcategory_id'=>$podcategory->id,])
                
                ->andWhere(['companies.active'=>1])
                ->orderBy('companies.balls DESC');
                
                if($session->has('area')){
                //Узнаем что за область
                $area = \common\models\Areas::find()->where(['url'=>$session->get('area')])->one();
                $query->andFilterWhere(['=', 'companies.area_id', $area->id]);
                $query->orFilterWhere(['=', 'filials.area_id', $area->id]);
            }
            
        $countQuery = clone $query;
        
        //подсчет контор
        $vsego = $countQuery->count();
        
        // подключаем класс Pagination, выводим по 10 пунктов на страницу
        $pages = new Pagination(['totalCount' => $vsego, 'pageSize' => 10]);
        // приводим параметры в ссылке к ЧПУ
        $pages->pageSizeParam = false;
        $company = $query->offset($pages->offset)
            ->limit($pages->limit)
            ->all();
            
            
 
ну дальше рендеринг вида и все.
quasar
Сообщения: 109
Зарегистрирован: 2014.10.22, 09:27

Re: Выборка с joinWith тормозит запрос

Сообщение quasar »

Сори туплю. Вывел запрос перед пагинатором. Вот полный запрос перед результирующим all()

Код: Выделить всё

SELECT `companies`.* FROM `companies` LEFT JOIN `relations_subcategory_company` ON `companies`.`id` = `relations_subcategory_company`.`company_id` LEFT JOIN `filials` ON `companies`.`id` = `filials`.`id_company` WHERE (((`relations_subcategory_company`.`subcategory_id`='760') AND (`companies`.`active`=1)) AND (`companies`.`area_id` = 15)) OR (`filials`.`area_id` = 15) ORDER BY `companies`.`balls` DESC LIMIT 10
quasar
Сообщения: 109
Зарегистрирован: 2014.10.22, 09:27

Re: Выборка с joinWith тормозит запрос

Сообщение quasar »

Кстати напрямую когда вставляю этот запрос в phpmyadmin - время вот: Отображение строк 0 - 9 (10 всего, Запрос занял 0.0261 сек.).

Но я вижу что больше всего жрет не сама выборка а count()
Для пагинатора мне надо узнать сколько всего будет в результате строк:

Код: Выделить всё

// делаем копию выборки
        $countQuery = clone $query;
        
        //подсчет контор
        $vsego = $countQuery->count(); 
В итоге дебагер Yii показывает что тратится время именно на подсчет
Изображение
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: Выборка с joinWith тормозит запрос

Сообщение samdark »

Тогда делайте EXPLAIN запросу с COUNT(*), раз это он тормозит.
quasar
Сообщения: 109
Зарегистрирован: 2014.10.22, 09:27

Re: Выборка с joinWith тормозит запрос

Сообщение quasar »

Вот EXPLAIN тормознутого каунта
Изображение
quasar
Сообщения: 109
Зарегистрирован: 2014.10.22, 09:27

Re: Выборка с joinWith тормозит запрос

Сообщение quasar »

Может стоит как то изменить запрос? Мне нужно получить все записи компаний с определьонной категории (relations_subcategory_company.subcategory_id = 5) в конкретном городе (companies.area_id = 15) и те в которых есть филиал в этом городе (filials.area_id = 15) Тоесть я по сути и слепил эти три таблицы в кучу джойном и пытаюсь сделать выборку с таким условием. Может подскажете какие варианты запроса попробовать?
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: Выборка с joinWith тормозит запрос

Сообщение samdark »

Код: Выделить всё

EXPLAIN SELECT `companies`.*
FROM `companies`
JOIN `relations_subcategory_company` ON `companies`.`id` = `relations_subcategory_company`.`company_id`
JOIN `filials` ON `companies`.`id` = `filials`.`id_company`
WHERE
    `companies`.`active`=1
    AND
    (
        `relations_subcategory_company`.`subcategory_id`='760'
        AND `companies`.`area_id` = 15
    )
        OR `filials`.`area_id` = 15
ORDER BY `companies`.`balls` DESC
LIMIT 10
quasar
Сообщения: 109
Зарегистрирован: 2014.10.22, 09:27

Re: Выборка с joinWith тормозит запрос

Сообщение quasar »

Sam Dark писал(а):

Код: Выделить всё

EXPLAIN SELECT `companies`.*
FROM `companies`
JOIN `relations_subcategory_company` ON `companies`.`id` = `relations_subcategory_company`.`company_id`
JOIN `filials` ON `companies`.`id` = `filials`.`id_company`
WHERE
    `companies`.`active`=1
    AND
    (
        `relations_subcategory_company`.`subcategory_id`='760'
        AND `companies`.`area_id` = 15
    )
        OR `filials`.`area_id` = 15
ORDER BY `companies`.`balls` DESC
LIMIT 10
А как при помощи where, andWhere, andFilterWhere делать скобки. Тоесть как вы объединили в скобки
AND  (
        `relations_subcategory_company`.`subcategory_id`='760'
        AND `companies`.`area_id` = 15
    )

Я так понимаю движок каким то своим чудо способом определяет как объединяют условия...
Ответить