Make WordPress Core

Opened 2 years ago

Last modified 2 years ago

#57906 new enhancement

Introduce `wp_cache_*_query()` helpers

Reported by: tillkruess's profile tillkruess Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version: 6.2
Component: Cache API Keywords:
Focuses: Cc:

Description

Ticket #57625 outlines the issue of the last_changed timestamp of cache groups changing often, resulting in new cache keys for the same query, while not (or only slowly) expiring old keys. On busy sites this can be large amounts of cache data.

Giving object cache implementation more information about cached queries and sql results could make deleting stale cache keys much more efficient for each individual backend.

Take this example:

<?php

$query = "SELECT p.ID FROM $wpdb->posts AS p $join $where $sort";
$key = md5( $query );

$last_changed = wp_cache_get_last_changed( 'posts' );

if ( $in_same_term ) {
    $last_changed .= wp_cache_get_last_changed( 'terms' );
}

$cache_key = "adjacent_post:$key:$last_changed";

$result = wp_cache_get( $cache_key, 'posts' );

The cache key adjacent_post:eecd152a77156d10fff6090cd03144c1:0.63115800 16784882730.54921700 1678488360 is pretty useless to an implementation.

Introducing a new helper wp_cache_get_latest() would give an object cache more to work with to perform near instant invalidation, even with 10 of millions of keys:

<?php

$query = "SELECT p.ID FROM $wpdb->posts AS p $join $where $sort";
$key = md5( $query );

$last_changed = array( wp_cache_get_last_changed( 'posts' ) );

if ( $in_same_term ) {
    $last_changed[] = wp_cache_get_last_changed( 'terms' );
}

$result = wp_cache_get_query( $key, $last_changed, 'adjacent_post', 'posts' );

This would tell the object cache:

  • The query hash $key
  • The last changed timestamp to delete older data only
  • The type adjacent_post, so wp_query of the same posts group doesn't need to be flushed

And the implementation can store these in a hash or sorted set, which makes invalidation instantaneous and low cost.

Making this a progressive enhancement is cheap and easy:

<?php

function wp_cache_get_query( $key, $last_changed, $type, $group ) {
    $last_changed = implode( '', $last_changed );
    return wp_cache_get( "$type:$key:$last_changed", $group );
}

function wp_cache_set_query( $key, $value, $last_changed, $type, $group ) {
    $last_changed = implode( '', $last_changed );
    return wp_cache_set( "$type:$key:$last_changed", $value, $group );
}

Change History (1)

#1 @tillkruess
2 years ago

I'd love feedback on this @spacedmonkey @johnjamesjacoby @peterwilsoncc @flixos90.

Note: See TracTickets for help on using tickets.