Make WordPress Core

Opened 8 weeks ago

Last modified 7 weeks ago

#64038 new defect (bug)

Cache miss for `WP_Term_Query`

Reported by: chouby's profile Chouby Owned by:
Milestone: Future Release Priority: normal
Severity: normal Version:
Component: Taxonomy Keywords: needs-patch
Focuses: performance Cc:

Description

On a WP fresh install (test made with WP 6.8.2).

  1. Activate Query Monitor
  2. Visit the posts list table
  3. Check that Query Monitor report a duplicate query coming from WP_Term_Query::get_terms():
SELECT t.term_id
FROM wp_terms AS t
INNER JOIN wp_term_taxonomy AS tt
ON t.term_id = tt.term_id
WHERE tt.taxonomy IN ('category')
ORDER BY t.name ASC

One call is coming from wp_dropdown_categories()
One call is coming from wp_terms_check_list()

Both functions are not using the same arguments for the call to get_terms() but result in the same DB query.

In the past, the cache key used to be computed based on arguments passed to get_terms(). It's now a combination of these arguments and the SQL statement. Maybe using only the sql statement would be sufficient.

Attachments (1)

Screenshot 2025-09-25 at 18.27.24.png (261.9 KB) - added by westonruter 7 weeks ago.
Duplicate query confirmed

Download all attachments as: .zip

Change History (5)

#1 @Chouby
8 weeks ago

  • Component changed from General to Taxonomy
  • Focuses performance added

@westonruter
7 weeks ago

Duplicate query confirmed

#2 @westonruter
7 weeks ago

  • Keywords reporter-feedback added
  • Milestone changed from Awaiting Review to Future Release

I added some logging after the $key is generated:

<?php
do_action( 'qm/debug', compact( 'key', 'cache_args', 'sql' ) );

This is the difference between the logging for the duplicate queries:

  • /tmp/

    old new  
    11Array
    22(
    3     [key] => 7e29979b0d775b6021a8f36e13aae8e5
     3    [key] => 5a24f652b8a6b799e1e6d7d7b6afceca
    44    [cache_args] => Array
    55        (
    66            [taxonomy] => Array
     
    4242                (
    4343                )
    4444
    45             [hierarchical] =>
     45            [hierarchical] => 1
    4646            [search] =>
    4747            [name__like] =>
    4848            [description__like] =>
    4949            [pad_counts] =>
    50             [get] => all
     50            [get] =>
    5151            [child_of] => 0
    5252            [parent] =>
    5353            [childless] =>

My concern is that perhaps a different post-processed query result is being cached. However, by adding other logging when the cache is set, this doesn't seem to be the case:

  • /tmp/

    old new  
    11Array
    22(
    3     [cache_key] => get_terms:7e29979b0d775b6021a8f36e13aae8e5
     3    [cache_key] => get_terms:5a24f652b8a6b799e1e6d7d7b6afceca
    44    [term_cache] => Array
    55        (
    66            [0] => 1

The cache key was most recently modified to remove a redundant parameter component in r59028, and previously in r55083.

Even back r37572 it was:

<?php
$key = md5( serialize( wp_array_slice_assoc( $args, array_keys( $defaults ) ) ) . serialize( $taxonomies ) . $query );

@Chouby When was the cache key just the SQL and not the args?

Last edited 7 weeks ago by SergeyBiryukov (previous) (diff)

#3 @Chouby
7 weeks ago

  • Keywords reporter-feedback removed

To my knowledge, the arguments have always been included. The SQL was introduced in WP 4.4 by r35120

Keeping only the SQL was a suggestion for the future that could solve this duplicate queries issue.

#4 @westonruter
7 weeks ago

  • Keywords needs-patch added

@Chouby ok, I was confused because in the description you said the args used to not be included:

In the past, the cache key used to be computed based on arguments passed to get_terms(). It's now a combination of these arguments and the SQL statement. Maybe using only the sql statement would be sufficient.

Maybe I misunderstood.

Note: See TracTickets for help on using tickets.