jericopulvera's avatar

Handling Load speed for 1 million posts.

I generated a 100k posts and I noticed that it takes so much time to load. how do I handle this?

This is how I get the posts. and I use Vue js v-for to list all the posts.

public function fetchPostList(Request $request)
    {
        // Get All The 100k posts
        $posts = Post::all();

        // Add calculated value to each posts
        foreach($posts as $post)
        {
            $followed = 1; 
            $interaction = 1; 
            $post->edge = $post->weight * ($followed + $interaction) * $post->time;
        }

        // Sort the posts descending basead on the calculated value
        $ranked = $posts->sortByDesc(function($post) {
            return sprintf('%-12s%s', $post->edge, $post->created_at);
        });

        // Make a paginator for all the posts
        $page = 1;
        $perPage = 15; 
        $pagination = new LengthAwarePaginator(
            $ranked->forPage($page, $perPage)->values(),
            count($ranked),
            $perPage,
            $page,
            ['path' => $request->url(), 'query' => $request->query()] 
        );

        return $pagination;
    }
0 likes
4 replies
martinbean's avatar

@Eco012390 It’s going to be slow because you’re issuing a query to fetch all posts!

What is $post->edge? Can that not be calculated and stored in a column? As it’s not very efficient to fetch every post from your database, calculate an “edge”, and then display just 15 of those 1 million records.

2 likes
jericopulvera's avatar

@martinbean so I should not use Post::all()?

  • How do I add the edge value? because I need it so the intended post will appear first on the newsfeed.
  • I'm trying to use edgerank algorithm.
martinbean's avatar
Level 80

So I should not use Post::all()?

@Eco012390 Well if you do, it’s going to issue a SELECT * FROM articles SQL statement, and if you have a million rows in your table then it’s going to be slow. Especially if you loop through results and do more calculation before rendering your view.

You can either create a “virtual” column as part of your query, or will need to save the “rank” against an article. Otherwise your app’s just going to get slower and slower. Looking at your code, you could query like:

SELECT articles.*, (articles.weight * (articles.followed + articles.interaction) * articles.created_at) AS edge FROM articles ORDER BY edge DESC LIMIT 0, 15

This will give you the first 15 articles, sorted in descending order by the edge value.

You’ll also need to look into indexes to ensure this query is as optimal as possible.

3 likes
jlrdw's avatar

Always a pleasure viewing these post. I may never understands above answer, but I saved it for reference.

Please or to participate in this conversation.