#58962 closed enhancement (fixed)
Provide a way to load multiple specific options with a single database request
Reported by: |
|
Owned by: |
|
---|---|---|---|
Milestone: | 6.4 | Priority: | normal |
Severity: | normal | Version: | |
Component: | Options, Meta APIs | Keywords: | has-patch has-unit-tests needs-dev-note |
Focuses: | performance | Cc: |
Description
WordPress's get_option()
function generally relies on making individual database requests for each option, however with the majority of options (in most cases) being autoloaded, i.e. fetched once with a single database request and then stored in (memory) cache.
The option autoloading approach has been helpful overall in minimizing database requests, however for many sites "excessive autoloading" (i.e. autoloading too many options) has led to problems, where lots of options are loaded in the frontend that are never used during these pageloads, which slows down load time performance. Sometimes the issue is even worse to the degree that certain object cache solutions cannot store the large amount of data anymore, which can lead to extremely slow performance due to the bug.
Part of the problem is lack of documentation around option autoloading, its implications and best practices. For example, options that are only used in very specific contexts, e.g. a specific WP Admin screen, should preferably not be autoloaded. Though as of today, while preferable from an overall performance perspective, there is a lack of alternatives for use-cases where multiple options are still needed: For example, if a plugin needs to load 5-10 options on their own WP Admin screen, simply recommending to not autoload them would lead to 5-10 database requests on that WP Admin screen, i.e. unnecessarily slowing down performance of that screen.
Therefore this ticket aims to provide a way to load (or prime in cache) multiple specific options with a single database request. This can be used as a reasonable alternative for use-cases like the above, encouraging to not use general option autoloading as a bandaid for the lack of another efficient way to load multiple options.
Change History (12)
This ticket was mentioned in PR #4970 on WordPress/wordpress-develop by @mukesh27.
6 weeks ago
#2
- Keywords has-patch added; needs-patch removed
Trac ticket: https://core.trac.wordpress.org/ticket/58962
This pull request adds new functions as described in the issue description. Once we agree with the functions' code and signature, I will add unit tests.
- [ ] Add tests to cover the change.
@mukesh27 commented on PR #4970:
6 weeks ago
#4
@felixarntz PR is ready for review.
@mukesh27 commented on PR #4970:
5 weeks ago
#6
Thank you, @felixarntz, for the detailed code review and unit tests assessment. I have addressed those in my recent commit.
@costdev, I appreciate your explanation on Slack regarding the points I had misunderstood. 🦸♂️
@mukesh27 commented on PR #4970:
5 weeks ago
#7
Thank you, @felixarntz, for addressing the questions posed by @joemcgill. I concur with your responses. Joe, could you kindly review them when you have a moment today, so that we may proceed with the commit. Many thanks!
@mukesh27 commented on PR #4970:
4 weeks ago
#8
Thanks @joemcgill and @felixarntz 👏
@flixos90 commented on PR #4970:
4 weeks ago
#10
Committed in https://core.trac.wordpress.org/changeset/56445
To address this problem, we have holistically two options: Either we provide a way to directly retrieve multiple options at once, e.g. a
get_options( $options )
function. Or we stick to focusing on the existingget_option()
for actually retrieving options, but provide a function to prime specific options, i.e. load them into the cache with a single database request - similarly to the autoloaded options ("alloptions") query, but for a specific set of options.I would propose the following solution to the problem:
prime_options( $options )
to which developers can pass an array of option names. The function will load all options into the cache with a single database query, except for those options that are already in cache (if any).$autoload = 'no'
. No changes would need to be made to how options are actually fetched, asget_option()
would function the same way as before - the values would simply be already in cache if primed before.The above function would be the central foundation, however we could consider implementing additional "wrapper" functions to facilitate specific use-cases, for example:
prime_options_by_group( $option_group )
may be useful as a wrapper forprime_options()
, allowing e.g. a plugin to prime all options registered with a specific option group. This would give the benefit of not having to remember/hard-code all option names in the priming function call, and it would tie in nicely with the existing Settings API, where option names have been a required parameter since its origin. The function would effectively get all option names in the given group and then callprime_options( $options )
with them.get_options( $options )
function may be useful to actually retrieve multiple options in one go. The function would effectively callprime_options( $options )
and thenget_option( $option )
for each of them, returning an array of key value pairs.While we could also implement a standalone
get_options( $options )
function as an alternative (i.e. not using another function to prime options), I consider that approach overly limiting, as it would require to basically duplicate lots of theget_option()
function's code, and it would be easy to miss some nuances. So focusing the new functionality on priming options while keeping the foundation for retrieving options untouched makes more sense IMO.