Ravel8 Which SQL query is better?

Asked 2 years ago, Updated 2 years ago, 41 views

There are two tables.
ArArticles
List of articles posted by users
FFavorites
List of articles that users have registered as favorites

The article and its information are registered in には.
② will have the id (main key of 1) and user ID of the article registered as your favorite in the column.

When extracting a list of favorites, you are unsure which of the following two methods to choose.

A proposal
②Obtained the article ID registered by the user from the .
After that, a list of articles is acquired from から on condition of the ID.

$article_ids=Favorite::where('user_id', $user_id)->pluck('article_id');
$articles=Article::whereIn('id', $article_ids)->get();

B proposal
A list of articles is acquired by combining と and を by an article ID on the condition of a user ID.

$articles=Favorite::leftJoin('articles', 'favorites.article_id', '=', 'articles.id')
->where('favorites.user_id', $user_id) ->get();

I'm concerned about the following:
(1) In such a case, which method is orthodox, A or B?
(2) Which one has better performance?
A has issued two SQL internally.
B performs the process of high cost combination.
(3) Which method is better overall?

Thank you for your cooperation.

sql laravel

2022-09-30 10:46

1 Answers

Fine-tune without permission.Also, start with :query() to make it compatible with IDE and easy to match indentation.

//A: Two consecutive SQL issues at WHERE IN (1, 2, 3, ...)
$article_ids=Favorite::query()
    ->where('user_id', $user_id)
    ->pluck('article_id');
$articles=Article::query()
    ->find($article_ids);

// B: Use JOIN
$articles=Article::query()
    ->leftJoin('favorites', 'favorites.article_id', '=', 'articles.id')
    ->where('favorites.user_id', $user_id)
    ->select('articles.*')
    ->get();

// C: Correlation subqueries using WHERE EXISTS (SELECT...)
$articles=Article::query()
    ->whereHas('favorites', function(Builder$query)use($user_id){
        $query->where('user_id'=>$user_id);
    })
    ->get();

// D: Non-relevant subqueries using WHERE IN (SELECT...)
// // https://github.com/mpyw/eloquent-has-by-non-dependent-subquery
$articles=Article::query()
    ->hasByNonDependentSubquery('favorites', function(Builder$query)use($user_id){
        $query->where('user_id'=>$user_id);
    })
    ->get();

A

It's the simplest code, but when you try to add pageation, you think a little more.Also, pageation is difficult with information only found in the articles table.Therefore, only a limited number of cases are available.

B

This is the best performance code, but it uses a lot of landmines.Please note the following:It's a good idea for non-skilled people to use it.

  • Only applicable.HasManyThere is a risk of duplicate records of the same ID appearing for the relationship.There is a limitation that says, "Only one user can like the same article," and there is no problem if you narrow it down to a single user_id.Also, HasOneBelongsTo is perfectly fine.
  • ->select('articles.*')Don't forget to give it.Without it, the favorites fields will be mixed into creating a disastrous bug.
  • Start with
  • Article::query().Favorite::query() results in an instance of Favorite.

C

Probably the most orthodox method.It can be used in many situations and is a safe method, but query optimizer is not smart MySQL, and the performance is blatantly degraded.There is no problem with PostgreSQL.

D

This code uses my own library to solve problems with C in MySQL.It's negative from an orthodox point of view, but it's both easy to use and high performance.


2022-09-30 10:46

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.