#26876 closed defect (bug) (fixed)
Default widgets causing unnecessary database queries
| Reported by: | codydh | Owned by: | wonderboymusic |
|---|---|---|---|
| Priority: | normal | Milestone: | 4.4 |
| Component: | Widgets | Version: | 3.0 |
| Severity: | minor | Keywords: | has-patch |
| Cc: | Focuses: |
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
@
13 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
@
11 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
@
11 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.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)
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.