Opened 7 years ago
Last modified 24 minutes ago
#46388 new enhancement
WP_User::get_data_by(): Cache non-existent users to prevent triggering multiple queries
| Reported by: |
|
Owned by: | |
|---|---|---|---|
| Milestone: | Future Release | Priority: | normal |
| Severity: | normal | Version: | 5.2 |
| Component: | Cache API | Keywords: | reporter-feedback has-patch has-unit-tests |
| Focuses: | performance | Cc: |
Description
Assume you use the WP_User::get_data_by() function to get the main user fields queried against an ID:
WP_User::get_data_by('ID', 1337);
If you call this function multiple times - by calling the function directly or indirectly by using functions like get_userdata or get_avatar - and an user with the given ID does not exist, the database-query is getting executed multiple times resulting in duplicate queries:
SELECT * FROM wp_users WHERE ID = '1337'
To prevent triggering multiple queries, non-existing users should get stored inside the WP Object Cache similar as in the get_option() function for non-existing options.
The attached patch checks if the user ID exists in the WP Object Cache inside of the notusers-array so the WP_User::get_data_by() function returns FALSE if this is the case:
// Prevent non-existent users from triggering multiple queries
$notusers = wp_cache_get( 'notusers', 'users' );
if ( isset( $notusers[ $user_id ] ) ) {
return false;
}
If the user is not existent in the notusers-array but he also does not exist inside of the database, the user gets added to the WP Object Cache before the WP_User:get_data_by() function returns FALSE:
// User does not exist, so we must cache its non-existence
if ( ! is_array( $notusers ) ) {
$notusers = array();
}
$notusers[ $user_id ] = true;
wp_cache_set( 'notusers', $notusers, 'users' );
Attachments (1)
Change History (4)
#1
follow-up:
↓ 2
@
5 years ago
- Keywords reporter-feedback added
Can we find ourselves in a situation where the ID is *created* after it's cached as non existent? If yes that operation should invalidate the cache.
#2
in reply to:
↑ 1
@
5 years ago
- Keywords needs-patch added; has-patch removed
- Milestone changed from Awaiting Review to Future Release
Replying to andraganescu:
Right, this ticket is a good idea but will need the "full" cache handling including cache busting or resetting on creating new user, etc.
This ticket was mentioned in PR #11632 on WordPress/wordpress-develop by @MythThrazz.
24 minutes ago
#3
- Keywords has-patch has-unit-tests added; needs-patch removed
Fixes https://core.trac.wordpress.org/ticket/46388
## Problem
When get_userdata() (or WP_User::get_data_by('id', $id)) is called for a non-existent user ID, it always executes a database query. If the same non-existent ID is looked up multiple times — for example, through repeated calls to get_userdata(), get_avatar(), or other functions that resolve user data — each call results in a duplicate SELECT * FROM wp_users WHERE ID = ... query.
## Solution
Cache non-existent user IDs in a notusers array within the users object cache group, following the established notoptions pattern from the options API (get_option()).
WP_User::get_data_by() (when $field === 'id'):
- Before querying the database, check the
notuserscache. Returnfalseimmediately if the ID is cached as non-existent. - After a database miss, add the ID to the
notuserscache.
update_user_caches():
- When a user is created or updated, remove their ID from the
notuserscache to ensure stale negative-cache entries are invalidated. This addresses the concern raised in comment:1 about cache invalidation on user creation.
The users cache group is already registered as a global group in multisite (wp_cache_add_global_groups()), so the notusers key inherits that scope correctly.
## Tests
Four new tests in tests/phpunit/tests/user/getDataBy.php:
- Verifies second call for a non-existent user triggers 0 DB queries.
- Verifies non-existent user ID is added to
notuserscache after first miss. - Verifies
notuserscache is invalidated whenupdate_user_caches()is called. - Verifies existing user IDs are never added to
notusers.
---
AI assistance: Yes
Tool(s): Claude Code (Anthropic)
Model(s): Claude Sonnet 4.6
Used for: Implementation and test authorship; reviewed and verified by contributor.
Add patch file for caching of non-existent users