Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

StackBoot's avatar

Laravel query tooo slow

I have the following filtering/grouping

    public function rows($organizationId, Request $request)
    {

        if (!$request->has('groupByItems')) {
            abort(404);
        }

        $groupByItems = json_decode($request->get('groupByItems'));

        $organization = auth()->user()->availableOrganizations()->findOrFail($organizationId);

        $query = PageViewEvent::where('page_view_events.organization_id', $organization->id);

        $select = $this->getSelect($groupByItems);

        $query->select($select);

        $query = $this->filterByPeriod($query, $request);

        $query = $this->grouping($query, $groupByItems);

        $query = $this->filterRows($query, $groupByItems, $request->input('filters'));

        $query = $this->dynamicSort($query, $request);

        $rows = $query->get(); 

        return response()->json(
            $rows
        );

    }

PageViewEvent model has 175K rows in database, which makes it really slow to load in front end I need to wait 44 secs for this to load.

All the filtering grouping its done using raw queries due to performance issues. Adding caching in top of this its just soo much hassle since user has a filter by period to filter data so its kind of redundant to some point!

I started even thinking of using elastic search for that model but that will require me to >rewrite the whole logic again!

*Anyone has any suggestion on how to optimize this a little bit more ? *

p.s for instance here is the select method

    protected function getSelect($groupByItems)
    {

        $select = "count({$this->model->getTable()}.id) as count,";

        if ($groupByItems->sessionId) {
            $select .= 'session_id,';
        }
        if ($groupByItems->referrer) {
            $select .= 'referrer,';
        }
        if ($groupByItems->trackingCode) {
            $select .= 'tracking_codes.code as tracking_code,';
            $select .= 'tracking_codes.label as tracking_label,';
        }
        if ($groupByItems->trackingSource) {
            $select .= 'ts.name as tracking_source,';
        }
        if (isset($groupByItems->path) && $groupByItems->path) {
            $select .= 'path,';
        }
        //if ($groupByItems->senderInfo->platform) {
        //    $select .= 'senders_info.platform as platform,';
        //}
        if ($groupByItems->senderInfo->device) {
            $select .= 'senders_info.device as device,';
        }
        if ($groupByItems->senderInfo->os) {
            $select .= 'senders_info.os as os,';
        }
        if ($groupByItems->senderInfo->browser) {
            $select .= 'senders_info.browser as browser,';
        }

        if (!empty($groupByItems->date)) {
            $select .= 'day(page_view_events.created_at) as date,';
        }

        if (!empty($groupByItems->weekday)) {
            $select .= 'dayname(page_view_events.created_at) as weekday,';
        }

        if (!empty($groupByItems->timeofday)) {
            $select .= 'hour(page_view_events.created_at) as timeofday,';
        }

        if (!empty($groupByItems->month)) {
            $select .= 'monthname(page_view_events.created_at) as month,';
        }

        $select .= $this->customSelectFields;

        return DB::raw(rtrim($select, ","));
    }

Same goes for grouping it uses raw db queries

Any help would be welcomed.

0 likes
6 replies
tykus's avatar

What is the query that actually runs from all of that setup?

Do you have an appropriate index on columns that your filters are being applied to?

Cronix's avatar

As well as your foreign keys, like organization_id? Your created_at fields? Just wait til you have millions of rows ;)

Any columns where there is a WHERE on, or ORDER BY, or GROUP BY should be indexed.

Please watch this excellent series with good examples. @fideloper shows all of the timings before and after indexing the proper columns. https://serversforhackers.com/laravel-perf/mysql-indexing-one

1 like
jlrdw's avatar

Group by is inherently slower anyway you need to get subsets of your data if possible only What is needed for example a monthly report rather than a annual report that sort of thing.

StackBoot's avatar

@Cronix actually thats what I ended up doing indexed some of the columns thanks for the guildance

StackBoot's avatar

@tykus actually thats only the top of iceberg, however I found a solution

tykus's avatar

Well, you can't expect specific answers to general questions; all we can offer is guidance...

Please or to participate in this conversation.