samedi 4 août 2018

Query is taking a long time to load

So I am doing a simple join and where/orwhere query,

I am trying to get friends and followers statuses:

$statuses = $this
    ->timeline
    ->select('timeline.*')
    ->friendsAndFollowers()
    ->orderBy('timeline.created_at', 'desc')
    ->paginate(10);

the methods friendAndFollowers returns a builder query:

/**
 * Scope a query to friends and followers statuses.
 *
 * @param \Illuminate\Database\Eloquent\Builder $query
 *
 * @return \Illuminate\Database\Eloquent\Builder
 */
public function scopeFriendsAndFollowers(Builder $query): Builder
{
    return $query
        ->leftJoin('followables', function ($join) {
            $join
                ->on('timeline.owner_id', '=', 'followables.followable_id')
                ->on('timeline.owner_type', '=', 'followables.followable_type');
        })
        ->leftJoin('friendships', function ($join) {
            $join
                ->on('timeline.owner_id', '=', 'friendships.recipient_id');
        })
        ->where(function ($query) {
            $query
                ->where('followables.user_id', auth()->user()->id, 'and')
                ->where('privacy', 'public')
                ->orWhere('privacy', 'private');
        })
        ->Orwhere(function ($query) {
            $query
                ->where(function ($query) {
                    $query
                        ->where('friendships.sender_id', Auth::user()->id)
                        ->orWhere('friendships.recipient_id', Auth::user()->id);
                })
                ->where('privacy', 'public')
                ->orWhere('privacy', 'private');
        })
        ->orWhere(function ($query) {
            $query
                ->where('timeline.owner_id', 1)
                ->where('timeline.owner_type', User::class);
        });
}

The database structure:

Friendships table:

    Schema::create(config('friendships.tables.fr_pivot'), function (Blueprint $table) {
        $table->increments('id');
        $table->morphs('sender');
        $table->morphs('recipient');
        $table->tinyInteger('status')->default(0);
        $table->timestamps();
    });

Followers table:

    Schema::create(config('follow.followable_table', 'followables'), function (Blueprint $table) {
        $table->unsignedInteger('user_id');
        $table->unsignedInteger('followable_id');
        $table->string('followable_type')->index();
        $table->string('relation')->default('follow')->comment('folllow/like/subscribe/favorite/');
        $table->timestamp('created_at');

        $table->foreign('user_id')
            ->references(config('follow.users_table_primary_key', 'id'))
            ->on(config('follow.users_table_name', 'users'))
            ->onUpdate('cascade')
            ->onDelete('cascade');
    });

Timeline table

    Schema::create('timeline', function (Blueprint $table) {
        $table->increments('id');
        $table->text('status')->nullable();
        $table->string('location')->nullable();
        $table->string('type')->nullable();
        $table->string('privacy')->default('public');
        $table->integer('owner_id');
        $table->string('owner_type');
        $table->timestamps();
        $table->softDeletes();
    });

Raw sql

SELECT `timeline`.* 
FROM   `timeline` 
       LEFT JOIN `followables` 
              ON `timeline`.`owner_id` = `followables`.`followable_id` 
                 AND `timeline`.`owner_type` = `followables`.`followable_type` 
       LEFT JOIN `friendships` 
              ON `timeline`.`owner_id` = `friendships`.`recipient_id` 
WHERE  ( ( `followables`.`user_id` = ? 
           AND `privacy` = ? 
            OR `privacy` = ? ) 
          OR ( ( `friendships`.`sender_id` = ? 
                  OR `friendships`.`recipient_id` = ? ) 
               AND `privacy` = ? 
                OR `privacy` = ? ) 
          OR ( `timeline`.`owner_id` = ? 
               AND `timeline`.`owner_type` = ? ) ) 

When I remove the last orWhere, it seems to speed it up, by a second or 2, when I remove all of it, it speeds up by 3 seconds (the query takes 4 seconds) which is far too much for a simple query, what do I seem to be doing wrong?



via Chebli Mohamed

Aucun commentaire:

Enregistrer un commentaire