Как оптимизировать sql запрос с несколькими Join-ами в ActiveQuery Yii2?

Запрос:

SELECT DISTINCT `announcements`.* FROM `announcements` 
LEFT JOIN `ann_categories` ON `announcements`.`ann_cat_id` = `ann_categories`.`id` 
LEFT JOIN `ann_subcategories` ON `announcements`.`ann_sub_cat_id` = `ann_subcategories`.`id` 
LEFT JOIN `ann_features_values` ON `announcements`.`id` = `ann_features_values`.`ann_id` 
WHERE `disabled` = 0 
ORDER BY `date_added` DESC 
LIMIT 15


Время выполнения - более 3-х секунд.

Explain показывает:

+----+-------------+---------------------+--------+--------------------------------------+--------------------------------------+---------+--------------------------------------------+-------+----------------------------------------------+
| id | select_type | table               | type   | possible_keys                        | key                                  | key_len | ref                                        | rows  | Extra                                        |
+----+-------------+---------------------+--------+--------------------------------------+--------------------------------------+---------+--------------------------------------------+-------+----------------------------------------------+
|  1 | SIMPLE      | announcements       | ref    | disabled,date_added_disabled         | disabled                             | 1       | const                                      | 50390 | Using where; Using temporary; Using filesort |
|  1 | SIMPLE      | ann_categories      | eq_ref | PRIMARY                              | PRIMARY                              | 2       | torgobmen_new.announcements.ann_cat_id     |     1 | Using index; Distinct                        |
|  1 | SIMPLE      | ann_subcategories   | eq_ref | PRIMARY                              | PRIMARY                              | 2       | torgobmen_new.announcements.ann_sub_cat_id |     1 | Using index; Distinct                        |
|  1 | SIMPLE      | ann_features_values | ref    | FK_ann_features_values_announcements | FK_ann_features_values_announcements | 5       | torgobmen_new.announcements.id             |     4 | Using index; Distinct                        |
+----+-------------+---------------------+--------+--------------------------------------+--------------------------------------+---------+--------------------------------------------+-------+----------------------------------------------+
4 rows in set (0.00 sec)


Запрос этот сгенерировал Yii2 и непонятен вообще смысл всех джойнов в данном запросе...

Код в контроллере (использован ActiveQuery):

$announcements = Announcements::find()
->joinWith('annCat')
->joinWith('annSubCat')
->joinWith('annFeaturesValues')
->where('`disabled` = 0');
 ->orderBy(['date_added' => SORT_DESC])
->limit(15)->distinct()->asArray()->all();


В результате я получаю массив $announcements в котором есть данные из связанных таблиц. (annCat, annSubCat... - это связи, которые есть в моделях). Все работает "как надо", но 3 секунды на выполнение - это очень много...
  • Вопрос задан
  • 439 просмотров
Пригласить эксперта
Ответы на вопрос 3
Inlore
@Inlore
Using temporary; Using filesort
говорит о том, что создаётся временная таблица, которая ещё и сортируется переборкой каждого поля.
Для disabled и date_added есть индексы?
Ответ написан
atillus
@atillus Автор вопроса
Работает супер-быстро, если убрать из запроса DISTINCT.
Но получаются сплошные дубли...
Использование вместо него "GROUP BY" - опять задействует Using temporary
Ответ написан
Комментировать
Melkij
@Melkij
PostgreSQL DBA
disabled и date_added - в таблице announcements

Так нафига вам вообще любой из указанных join'ов равно как и distinct?!
Вы из них абсолютно никак не читаете и не используете. Так зачем? Просто размножить строки и героически их склеить обратно distinct'ом?

SELECT `announcements`.* FROM `announcements` 
WHERE `disabled` = 0 
ORDER BY `date_added` DESC 
LIMIT 15
Ответ написан
Ваш ответ на вопрос

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

Похожие вопросы