1

I have been told that using this in the array:

'orderby'  => 'rand'

will cause this:

Ordering by random is extremely expensive to query, involving creating temporary database tables, and scans, as it has to copy the entire posts table, then randomly re-order the posts, then finally do the actual query on the new table before destroying it.

And I have been advised:

It's much easier to ask for the first post that occurs after a random date.

Can anyone elaborate on this?

Is there an array code line that will do the above?

Any resource regarding this would be very appreciated.

2 Answers 2

1

If something needs to be "random" than the last post ( or the one before last ) will answer that definition well enough. Just because you know it is not a post generated by a randomizing algorithm do not mean it is not random to the user.

There is just no way to have a "truely" random post if you care about performance, and that is before even discussing page caching.

4
  • I see. Actually I need to be a completely random. Since I want all of the posts be seen equally for all users. What amount of posts with 'rand' is truly starts to become a performance problem? I will probably have around 500 posts max at first. Later would be more than willing to change the hosting for better perfomance.
    – robert0
    Commented Sep 18, 2021 at 8:56
  • The more posts you have the more impact it will have on the performance. The smaller the number of posts you want to get this way the better. Part of the problem is that the posts table is full with revisions, attachments and who knows what else, therefor when you ask the DB to get a random row it might need to create a selection of rows that fits your requirements and select from them. Commented Sep 18, 2021 at 9:27
  • The canonical answer for getting randomized post is to do it on the PHP side, store a list of post IDs from which you want to randomize (maybe in a transient) and select a random item from the list and do a get_post for it. Commented Sep 18, 2021 at 9:28
  • Got it. Thanks for the advice!
    – robert0
    Commented Sep 18, 2021 at 9:52
1

Retrieving the first post published after a random date can be achieved with a WordPress date query combined with the wp_rand() function.

For the wp_rand() function, you just have to supply it the minimum and maximum number. We can use this function to return a random timestamp between the current time and the timestamp of the first published post. The function time() will give the current time as a unix timestamp and this could be your maximum number. For the minimum number, the timestamp of the first published post could be used.

This minimum number could be hardcoded, since it's unlikely to change, but if you wanted to run a query to find the timestamp of the first published post, that would look like this:

        $first_post_query = new \WP_Query( [
            'post_type' => 'post',
            'post_status' => 'publish',
            'posts_per_page' => 1,
            'orderby' => 'date',
            'order' => 'ASC',
            'ignore_sticky_posts' => true,
            'no_found_rows'       => true,
        ] );
        $first_post = $first_post_query->posts[0];
        $min_time = strtotime( $first_post->post_date_gmt ) + 1;

Now that we have a minimum number, we can calculate a random timestamp and convert it into a date like this:

        $random_timestamp = wp_rand( $min_time, time() );
        $random_date = date( 'm/d/Y H:i:s', $random_timestamp );

This random date can be used in a WP_Query to retrieve a random post:

        $query = new \WP_Query( [
            'post_type' => 'post',
            'post_status' => 'publish',
            'posts_per_page' => 1,
            'date_query' => [
                'before' => $random_date,
            ],
            'ignore_sticky_posts' => true,
            'no_found_rows'       => true,
        ] );
        $random_post = $query->posts[0];

The ignore_sticky_posts and no_found_rows parameters are to improve the performance of the query.

I would expect this query to return fairly random posts for a site with regularly spaced out content. For example, if posts were published consistently every day over the time period in question. However, if the publishing cadence was erratic, then this would produce suboptimal results.

2
  • Thanks for such an in depth answer, Linnea. Now I got the point of what the other fellow coder meant by querying by a random date. This is interesting, and will work in my situation with a couple of adjustments. Thanks again!
    – robert0
    Commented Sep 22, 2021 at 14:12
  • 1
    You're welcome! Another possible solution could be to set a random offset parameter instead of randomizing the date. See WP_Query documentation. Commented Sep 23, 2021 at 13:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.