#26876 closed defect (bug) (fixed)
Default widgets causing unnecessary database queries
Reported by: | codydh | Owned by: | wonderboymusic |
---|---|---|---|
Milestone: | 4.4 | Priority: | normal |
Severity: | minor | Version: | 3.0 |
Component: | Widgets | Keywords: | has-patch |
Focuses: | Cc: |
Description
I wasn't able to find this bug reported, so I hope it's not a duplicate. Apologies in advance if it is!
It seems that WordPress is checking the options table of the database for four widgets, widget_pages, widget_calendar, widget_tag_cloud, and widget_nav_menu, even when these widgets aren't activated, and even when the theme has no widget area:
Query: SELECT option_value FROM xy_options WHERE option_name = 'widget_pages' LIMIT 1 Query: SELECT option_value FROM xy_options WHERE option_name = 'widget_calendar' LIMIT 1 Query: SELECT option_value FROM xy_options WHERE option_name = 'widget_tag_cloud' LIMIT 1 Query: SELECT option_value FROM xy_options WHERE option_name = 'widget_nav_menu' LIMIT 1
One easy fix is to add the following lines to functions.php:
add_action( 'widgets_init', 'remove_unneeded_widgets' ); function remove_unneeded_widgets() { unregister_widget('WP_Widget_Pages'); unregister_widget('WP_Widget_Calendar'); unregister_widget('WP_Widget_Tag_Cloud'); unregister_widget('WP_Nav_Menu_Widget'); }
Much of this information was corroborated by a StackExchange post (http://wordpress.stackexchange.com/questions/81785/remove-unnecessary-mysql-query/82420#82420) from early 2013, indicating this may have been around for a while.
Attachments (4)
Change History (15)
#2
@
11 years ago
- Keywords has-patch added; needs-patch removed
Nice catch! This is not only related to core widgets. Any registered widget without a database entry will fire a query during widgets_init
. We could solve it for core widgets by adding some fields to populate_options()
, however I think we can do better than that :)
During _register()
we really only need that setting to determine how many times _register_one()
should be called, so for widgets that haven't been used (not in a sidebar and not in the inactive widgets array, and no db entry) that's always one.
26876.diff attempts to fix this with is_active_widget()
.
This does mean that an additional regex will run during widgets_init
for every available widget, but I don't think that will ever be a concern since we use _get_widget_id_base
and the regex is most likely cached by then.
#4
@
9 years ago
Note that I think it would be ideal for performance reasons if widgets were only registered if they are active for the current context, i.e. after sidebars_widgets
has been filtered or when dynamic_sidebar
is called. I'm working on a site that has hundreds of widgets, maybe thousands when factoring in inactive widgets, and yet only a dozen are actually used on a given page.
#6
@
9 years ago
26876.3.patch would have WP_Widget::get_settings()
call WP_Widget::save_settings()
with an empty array when no option is found in the database and the alt_option_name
property isn't set. On the next request, the widget option would be autoloaded and not generate another query.
I've noticed this too. It's caused by the fact that these options aren't present in the database by default, which means they're not present in the array returned by
wp_load_all_options()
, which meansget_option()
falls back to a second database query to look for the value.Off the top of my head, we could solve this by inserting a default option value for each of these keys (in the upgrade routine), or we could avoid trying to fetch options for widgets that aren't in use.