Home Forums General Issues get_posts filtered by custom field very slow Reply To: get_posts filtered by custom field very slow

  • Reading in 10k posts and then looping over them will likely cause other issues with performance due to the data returned in the query and memory.

    The biggest issue to speed is that regex on the date and the number of fields your using to filter.

    If I needed to do something similar to this and knew it before I started I would have a separate field (not in ACF, just your standard WP custom meta field). I would create and acf/save_post filter. In this filter I would get the date field, extract the year and save just the year into this other field. The I could do a simple ‘==’ compare on this field. This would greatly improve the performance of the query.

    But with 10k posts to look at it might still be a little slow. If it was I would likely use WP transients to store the results of the query for a time. This would mean the query would only need to be run once every few days.

    You could also have a taxonomy for the year, as in one of the points you listed, with the right settings you can actually hide this taxonomy. Instead of saving the year in another fields as in my first suggestion the acf/save_post filter would set the correct term in the year taxonomy.

    Post meta can be used for filtering, however, the filtering needs to be limited and the use of things like “LIKE” and “REGEXP” are going to cause performance issues.

    I also have one site, this site has “Products” and there are (no lie) 18 different filters used on this site. Trying to filter by 18 custom fields would simply time out the load of the page. In this case, when a new “Product” is saved a CRON is triggered. This CRON runs through all of the possible values for every filter and stores the results. On the front end of the site I use this information to query the posts.

    Use a WP option, lets call this option “birth_years”. This option would be an array with this architecture.

    $birth_years = array (
      // each element of this array is "YEAR" => array()
      "2020" => array (
        // each element of this array is a post ID of a person in this year
        1, 2, 3, 4, 5

    Create an acf/save_post filter with a priority of 1 so that it runs before ACF saves the value of the date field. See the doc for this filter. In this filter I would compare the old value with the new value. If it is the same I would do nothing. If it is different I would get the option, remove this person’s post ID from the old year and add it to the new year in my array.

    Then when doing the query for people in the same year I would get the option add this to my query

    'post__in' => $birth_year['2020']

    completely eliminating the meta query.

    Hope some of this information helps you