Home » Php » How to prevent unnecessary queries when (lazy) eager loading?

How to prevent unnecessary queries when (lazy) eager loading?

Posted by: admin October 29, 2018 Leave a comment

Questions:

I wrote a function that aggregates and transforms data to pass to a View.

It looks like this

public function transformToArray(Page $page): array
{
    $image = new CloudImage($page->category_img, ImageDirectory::ARTICLE, $page->article->art_titel);

    return [
        'article' => [
            'title' => $page->pageSpecification->title,
            'text' => strip_tags_to_html($page->pageSpecification->text, session('t_ID')),
            'image' => $image,
            'related_products' => $page->article->relatedProducts->transform(function (Product $product) {
                    return [
                        'id' => $product->prod_ID,
                        'url' => secure_url($product->slug->hd_name) . '/',
                        'name' => $product->productSpecification->pl_naam,
                        'image_url' => $product->imageLink->image->getImageObject()->getUrl(),
                        'short_description' => $product->productSpecification->pl_shtag,
                    ];
            }),
            'related_articles' => $page->article->relatedArticles->transform(function (Article $article) {
                    return [
                        'title' => $article->art_titel,
                        'url' => secure_url($article->slug->hd_name) . '/',
                    ];
            }),
        ],
    ];
}

If this look very complex, don’t worry: it isn’t!

What happens here is passing a Model (object) to this function that is queried by slug (the url). And I load some relationships in this function that contain data I need on this specific View. Nothing special.

However my problem is that this code generates way too many queries

select * from `slugs` where (`slug` = 'niesziekte-bij-katten' and `language_id` = '1') limit 1
select * from `page` where `page_id` = '1072' limit 1
select * from `page` where `page`.`page_id` = '1072' and `page`.`page_id` is not null limit 1
select * from `page_lang` where `lang_id` = '1' and `page_lang`.`page_id` in ('1072')
select * from `page_relation` where `page_relation`.`parent` in ('1072')
select * from `page_relation` where `page_relation`.`child` in ('1072')
select * from `artikelen` where `artikelen`.`art_set_ID` = '62' and `artikelen`.`art_set_ID` is not null and `artikelen`.`art_lang_ID` = '1' limit 1
select `product`.*, `product_attribute_product_koppel`.`pa_id` from `product` inner join `product_attribute_product_koppel` on `product_attribute_product_koppel`.`prod_id` = `product`.`prod_ID` where `product_attribute_product_koppel`.`pa_id` in ('1072')
select * from `slugs` where `language_id` = '1' and `slugs`.`hd_pID` in ('551', '596', '1390', '2517', '2564', '2773', '2845', '3009', '3248', '3249', '3414', '3968', '4666', '5310', '5311', '5313', '5510', '5864', '5868', '5869')
select * from `product_lang` where `pl_lang_ID` = '1' and `product_lang`.`pl_prod_ID` in ('551', '596', '1390', '2517', '2564', '2773', '2845', '3009', '3248', '3249', '3414', '3968', '4666', '5310', '5311', '5313', '5510', '5864', '5868', '5869')
select `product`.*, `product_artikelen_koppeling`.`pak_art_ID` from `product` inner join `product_artikelen_koppeling` on `product_artikelen_koppeling`.`pak_prod_ID` = `product`.`prod_ID` inner join `product_lang` on `product_lang`.`pl_prod_ID` = `product`.`prod_ID` where `product_artikelen_koppeling`.`pak_art_ID` = '123' and `product_lang`.`pl_lang_ID` = '1' and `product_lang`.`pl_onoff` = '1' and `product_lang`.`pl_restrict_promo_intern` = '0'
select * from `slugs` where `slugs`.`hd_pID` = '1297' and `slugs`.`hd_pID` is not null and `language_id` = '1' limit 1
select * from `product_lang` where `product_lang`.`pl_prod_ID` = '1297' and `product_lang`.`pl_prod_ID` is not null and `pl_lang_ID` = '1' limit 1
select * from `product_img_koppel` where `product_img_koppel`.`prod_ID` = '1297' and `product_img_koppel`.`prod_ID` is not null and `product_img_koppel`.`lang_ID` = '1' and `product_img_koppel`.`main_yn` = '1' limit 1
select * from `product_img` where `product_img`.`pi_parent_ID` = '78991' and `product_img`.`pi_parent_ID` is not null limit 1
select * from `slugs` where `slugs`.`hd_pID` = '402' and `slugs`.`hd_pID` is not null and `language_id` = '1' limit 1
select * from `product_lang` where `product_lang`.`pl_prod_ID` = '402' and `product_lang`.`pl_prod_ID` is not null and `pl_lang_ID` = '1' limit 1
select * from `product_img_koppel` where `product_img_koppel`.`prod_ID` = '402' and `product_img_koppel`.`prod_ID` is not null and `product_img_koppel`.`lang_ID` = '1' and `product_img_koppel`.`main_yn` = '1' limit 1
select * from `product_img` where `product_img`.`pi_parent_ID` = '86410' and `product_img`.`pi_parent_ID` is not null limit 1
select * from `slugs` where `slugs`.`hd_pID` = '2527' and `slugs`.`hd_pID` is not null and `language_id` = '1' limit 1
select * from `product_lang` where `product_lang`.`pl_prod_ID` = '2527' and `product_lang`.`pl_prod_ID` is not null and `pl_lang_ID` = '1' limit 1
select * from `product_img_koppel` where `product_img_koppel`.`prod_ID` = '2527' and `product_img_koppel`.`prod_ID` is not null and `product_img_koppel`.`lang_ID` = '1' and `product_img_koppel`.`main_yn` = '1' limit 1
select * from `product_img` where `product_img`.`pi_parent_ID` = '8092' and `product_img`.`pi_parent_ID` is not null limit 1
select * from `artikelen` inner join `slugs` on `artikelen`.`art_set_ID` = `slugs`.`hd_art_set_ID` and `artikelen`.`art_lang_ID` = `slugs`.`language_id` where `artikelen`.`artikel_categorie_id` = '25' and `artikelen`.`artikel_categorie_id` is not null and `art_lang_ID` = '1' and `art_aan_uit` = '1' and `art_ID` != '123' order by `art_jaar` desc, `art_maand` desc, `art_dag` desc limit 10
select * from `slugs` where `slugs`.`hd_art_set_ID` = '60' and `slugs`.`hd_art_set_ID` is not null and `language_id` = '1' limit 1
select * from `slugs` where `slugs`.`hd_art_set_ID` = '61' and `slugs`.`hd_art_set_ID` is not null and `language_id` = '1' limit 1
select * from `slugs` where `slugs`.`hd_art_set_ID` = '19' and `slugs`.`hd_art_set_ID` is not null and `language_id` = '1' limit 1

Especially that last few queries make me wonder why it does not use more in (1, 2, 3) queries like it does before to eager load. Is there some way to optimize this code to do so? I prefer not to use the query builder, because I want my relation queries to be reusable.

Answers: