There are a few things that can be done to optimize this query:
-
Add indexes to the columns used in the WHERE and JOIN clauses. In this case, it would be beneficial to add indexes to the following columns:
tracking_views.user_id,users.id,users.company_id,companies.id,tracking_views.created_at,tracking_views.viewable_type, andtracking_views.viewable_id. -
Use eager loading to reduce the number of queries being executed. In this case, it would be beneficial to eager load the
userandcompanyrelationships. -
Use pagination to limit the number of records being returned. In this case, the query is already using pagination, but it may be beneficial to reduce the number of records being returned per page.
Here's an updated version of the query that incorporates these optimizations:
$query = TrackingView::query()
->select([
'tracking_views.id as id',
'tracking_views.created_at as created_at',
'users.id as user_id',
'users.name as user_name',
'users.email as user_email',
'companies.id as company_id',
'companies.name as company_name',
])
->leftJoin('users', 'tracking_views.user_id', '=', 'users.id')
->leftJoin('companies', 'users.company_id', '=', 'companies.id')
->with('user', 'user.company')
->where(function ($query) {
$query->whereNull('tracking_views.user_id')
->orWhereHas('user', function ($query) {
if (!is_empty_string($this->userSearch)) {
$query->where(function ($query) {
$query->where('name', 'like', '%' . $this->userSearch . '%')
->orWhere('email', 'like', '%' . $this->userSearch . '%')
->orWhereHas('company', function ($query) {
$query->where('name', 'like', '%' . $this->userSearch . '%');
});
});
}
});
})
->when(isset($this->viewable), function ($query) {
$query->where('viewable_type', get_class($this->viewable))
->where('viewable_id', $this->viewable->id);
})
->when(isset($this->startDate) && isset($this->endDate), function ($query) {
$query->whereBetween('tracking_views.created_at', [$this->startDate, $this->endDate]);
})
->orderBy($this->sortField, $this->sortDirection)
->paginate(10, ['*'], 'postViewsPage');
Note that I've also simplified the switch statement by using the when method.