WordPress.org

Make WordPress Core

Opened 3 weeks ago

Closed 2 weeks ago

#54459 closed enhancement (duplicate)

Give get_option a third parameter to prevent DB queries

Reported by: joostdevalk Owned by:
Milestone: Priority: normal
Severity: normal Version:
Component: Options, Meta APIs Keywords: has-patch 2nd-opinion
Focuses: Cc:

Description

If you start looking for queries to optimize on any random WordPress site, you'll find queries like this:

SELECT option_value FROM bphtc_options WHERE option_name = 'WPLANG' LIMIT 1

where this happens for WPLANG, but also for lots of other options. This only happens when the option doesn't exist, because core already does this query before all of them:

SELECT option_name, option_value FROM bphtc_options WHERE autoload = 'yes'

Because it does that, we can prevent queries like the former to happen entirely if we know that it *should* be auto loaded. To be able to do that we should add a third parameter to get_option() that allows us to say "don't fallback to a database query if this option wasn't auto loaded".

Change History (4)

This ticket was mentioned in PR #1907 on WordPress/wordpress-develop by jdevalk.


3 weeks ago

Most developers don't realize that when they use get_option() and the option doesn't exist or isn't auto-loaded, this causes a query to the database. This patch allows developers that want to prevent this from happening to prevent that.

This doesn't change any default behavior, but does allow adding a third parameter to prevent a fallback database query.

Trac ticket: 54459

#2 @desrosj
3 weeks ago

  • Keywords 2nd-opinion added

I took a look and reacquainted with how get_option() works because I feel like this has come up somewhere for me in the past.

It seems there are a few ways to accomplish this already. Because this change would be an opt-in change, I'm wondering if these are better options because they don't require additional arguments to be added.

  • Using the pre_cache_alloptions filter, someone could check ! isset( $alloptions['myoption'] ) and add the default value for that option. wp_load_alloptions() fetches all options with autoload = 'yes' (unless there are no options set to autoload).
  • At some point during the bootstrap process after wp_load_alloptions() has been called (or after calling it early on), a dev could run code that checks the keys present in the alloptions cache, and add their own known autoload options with default values before updating that cache.
  • The same as previous, a dev could add their keys to the notoptions cache, and the function would fall back to returning the passed default value without a query.

Personally, I like option 3 because it allows a different default to be passed in different locations where get_option() is called if desired. A filter could be probably be added to allow someone to adjust the notoptions cache before it's updated to make this easier.

Another way to protect these extra queries is to have a list of registered options. But this is really the same thing as the alloption list, except it would include the ones that don't currently exist.

#3 @PieWP
3 weeks ago

@joostdevalk get_option contains a recursion on line 109 maybe you want to update your patch to also pass the parameter there.

@desrosj yes there are multiple ways, but they require more effort than simply passing a third argument doing all the logic for you. My current workaround consists of checking the wp cache, if its not cached it was not autoloaded.

What I'm wondering though is how do we feel about consistency, if it is decided that @joostdevalk proposition is an elegant solution should that also be trickled down to other option methods? ( get_blog_option, get_site_option, get_network_option )

Last edited 3 weeks ago by PieWP (previous) (diff)

#4 @SergeyBiryukov
2 weeks ago

  • Milestone Awaiting Review deleted
  • Resolution set to duplicate
  • Status changed from new to closed

Hi there, thanks for the ticket!

It looks like this has been previously proposed in #37178, let's continue the discussion there.

Note: See TracTickets for help on using tickets.