#optimize slow query

1 messages · Page 1 of 1 (latest)

floral jasper
#

is there a way to optimize this query?

Applicant::query()->with('interviews', 'interviews.jobListing', 'latestEducationHistory')
            ->when($search, function ($q) use ($search) {
                $q->whereAny($fields, 'LIKE', "%{$search}%");
            })->when($status, fn ($q) => $q->where('status', $status))
            ->when(! $onlyRejected, fn ($q) => $q->where('status', '!=', ApplicantStatus::Rejected))
            ->when($onlyRejected, fn ($q) => $q->where('status', '=', ApplicantStatus::Rejected))
            ->when($startYearBorn, fn ($query) => $query->whereYear('date_of_birth', '>=', $startYearBorn))
            ->when($endYearBorn, fn ($query) => $query->whereYear('date_of_birth', '<=', $endYearBorn))
            ->when($cityId, fn ($q) => $q->where('city_id', $cityId))
            ->when($positionAppliedId, fn ($query) => $query->whereRelation('interviews', 'job_listing_id', '=', $positionAppliedId))
            ->when($startDate, fn ($query) => $query->whereRelation('interviews', 'created_at', '>=', $startDate))
            ->when($endDate, fn ($query) => $query->whereRelation('interviews', 'created_at', '<=', $endDate))
            ->when($statuses, fn ($q) => $q->whereIn('status', $statuses))
            ->where('status', '!=', ApplicantStatus::ConvertedToEmployee)
            ->select('applicants.*')
            ->leftJoin('applicant_education_histories as latest_education', function ($join) {
                $join->on('applicants.id', '=', 'latest_education.applicant_id')
                    ->whereRaw('latest_education.graduate_year = (SELECT MAX(graduate_year) FROM applicant_education_histories WHERE applicant_id = applicants.id)');
            })
            ->orderBy('latest_education.gpa', $sortGpa == 'desc' ? 'desc' : 'asc')
#

there's 3 line that bother me

->when($positionAppliedId, fn ($query) => $query->whereRelation('interviews', 'job_listing_id', '=', $positionAppliedId))
->when($startDate, fn ($query) => $query->whereRelation('interviews', 'created_at', '>=', $startDate))
->when($endDate, fn ($query) => $query->whereRelation('interviews', 'created_at', '<=', $endDate))

can i do this in 1 query. that will translate

where exists(select * from applicant_interviews where ...) and exists (select * from applicant_interviews where ...)

both has same table

#

the query above cost 500-1.2k ms. the requirement should achieve <500ms for that query

astral moon
#

tried using explain at the query? perhaps indexing those columns might help