Make WordPress Core

Opened 3 days ago

Last modified 12 hours ago

#64090 assigned enhancement

Unexpected DB query when inserting a non-hierarchical term

Reported by: chouby's profile Chouby Owned by: spacedmonkey's profile spacedmonkey
Milestone: 6.9 Priority: normal
Severity: normal Version:
Component: Taxonomy Keywords: needs-unit-tests good-first-bug has-patch
Focuses: performance Cc:

Description

When inserting a new non-hierarchical term, an unexpected query (valid for hierarchical terms) is uselessly made. Example for post tags:

SELECT autoload FROM wptests_options WHERE option_name = 'post_tag_children'

This test allows to easily reproduce the issue.

<?php
        public function test_unexpected_query_wp_insert_term() {
                global $wpdb;

                define( 'SAVEQUERIES', true );

                wp_insert_term( 'test', 'post_tag' );

                $queries = array_column( $wpdb->queries, 0 );
                $search  = array_search( "SELECT autoload FROM wptests_options WHERE option_name = 'post_tag_children'", $queries );
                $this->assertFalse( $search );
        }

This useless query comes from the clean_taxonomy_cache() which always calls delete_option( "{$taxonomy}_children" ); regardless of the existence of this option.

Change History (5)

#1 @spacedmonkey
3 days ago

  • Keywords needs-patch needs-unit-tests good-first-bug added
  • Milestone changed from Awaiting Review to 4.9
  • Type changed from defect (bug) to enhancement

The fix here seems like a simple one.

Update clean_taxonomy_cache.

function clean_taxonomy_cache( $taxonomy ) {
...

        // Regenerate cached hierarchy.
        if ( ! is_taxonomy_hierarchical( $taxonomy ) ) {
           delete_option( "{$taxonomy}_children" );
           _get_term_hierarchy( $taxonomy );
        }
...
}

Adding a good-first-bug, as this is a quick fix.

This ticket was mentioned in PR #10216 on WordPress/wordpress-develop by @Chouby.


3 days ago
#2

  • Keywords has-patch added; needs-patch removed

Removes a useless DB query (made by delete_option()) for non-hierarchical taxonomies when cleaning the taxonomy cache.

Trac ticket: https://core.trac.wordpress.org/ticket/64090

#3 @sabernhardt
3 days ago

  • Milestone changed from 4.9 to 6.9

#4 @westonruter
2 days ago

  • Owner set to spacedmonkey
  • Status changed from new to assigned

#5 @rollybueno
45 hours ago

Run the test on both trunk and https://github.com/WordPress/wordpress-develop/pull/10216/. The difference is that, on trunk we got extra query, which confirms the issue reproduction:

SELECT autoload FROM wptests_options WHERE option_name = 'post_tag_children'

while on the https://github.com/WordPress/wordpress-develop/pull/10216/ we got none. Below is the before and after test result, printing the queries:

trunk:

Array
(
    [0] => SELECT  t.term_id
                         FROM wptests_terms AS t  INNER JOIN wptests_term_taxonomy AS tt ON t.term_id = tt.term_id
                         WHERE tt.taxonomy IN ('post_tag') AND t.name IN ('test') AND tt.parent = '0'
                         ORDER BY t.name ASC
                         
    [1] => SELECT  t.term_id
                         FROM wptests_terms AS t  INNER JOIN wptests_term_taxonomy AS tt ON t.term_id = tt.term_id
                         WHERE t.slug IN ('test')
                         ORDER BY t.term_id ASC
                         LIMIT 1
    [2] => SELECT  t.term_id
                         FROM wptests_terms AS t  INNER JOIN wptests_term_taxonomy AS tt ON t.term_id = tt.term_id
                         WHERE t.name IN ('test')
                         ORDER BY t.term_id ASC
                         LIMIT 1
    [3] => INSERT INTO `wptests_terms` (`name`, `slug`, `term_group`) VALUES ('test', 'test', 0)
    [4] => SELECT tt.term_taxonomy_id FROM wptests_term_taxonomy AS tt INNER JOIN wptests_terms AS t ON tt.term_id = t.term_id WHERE tt.taxonomy = 'post_tag' AND t.term_id = 5
    [5] => INSERT INTO `wptests_term_taxonomy` (`term_id`, `taxonomy`, `description`, `parent`, `count`) VALUES (5, 'post_tag', '', 0, 0)
    [6] => SELECT t.term_id, t.slug, tt.term_taxonomy_id, tt.taxonomy FROM wptests_terms AS t INNER JOIN wptests_term_taxonomy AS tt ON ( tt.term_id = t.term_id ) WHERE t.slug = 'test' AND tt.parent = 0 AND tt.taxonomy = 'post_tag' AND t.term_id < 5 AND tt.term_taxonomy_id != 5
    [7] => SELECT autoload FROM wptests_options WHERE option_name = 'post_tag_children'
)

PR 10216:

Array
(
    [0] => SELECT  t.term_id
                         FROM wptests_terms AS t  INNER JOIN wptests_term_taxonomy AS tt ON t.term_id = tt.term_id
                         WHERE tt.taxonomy IN ('post_tag') AND t.name IN ('test') AND tt.parent = '0'
                         ORDER BY t.name ASC
                         
    [1] => SELECT  t.term_id
                         FROM wptests_terms AS t  INNER JOIN wptests_term_taxonomy AS tt ON t.term_id = tt.term_id
                         WHERE t.slug IN ('test')
                         ORDER BY t.term_id ASC
                         LIMIT 1
    [2] => SELECT  t.term_id
                         FROM wptests_terms AS t  INNER JOIN wptests_term_taxonomy AS tt ON t.term_id = tt.term_id
                         WHERE t.name IN ('test')
                         ORDER BY t.term_id ASC
                         LIMIT 1
    [3] => INSERT INTO `wptests_terms` (`name`, `slug`, `term_group`) VALUES ('test', 'test', 0)
    [4] => SELECT tt.term_taxonomy_id FROM wptests_term_taxonomy AS tt INNER JOIN wptests_terms AS t ON tt.term_id = t.term_id WHERE tt.taxonomy = 'post_tag' AND t.term_id = 5
    [5] => INSERT INTO `wptests_term_taxonomy` (`term_id`, `taxonomy`, `description`, `parent`, `count`) VALUES (5, 'post_tag', '', 0, 0)
    [6] => SELECT t.term_id, t.slug, tt.term_taxonomy_id, tt.taxonomy FROM wptests_terms AS t INNER JOIN wptests_term_taxonomy AS tt ON ( tt.term_id = t.term_id ) WHERE t.slug = 'test' AND tt.parent = 0 AND tt.taxonomy = 'post_tag' AND t.term_id < 5 AND tt.term_taxonomy_id != 5
)

Hey @Chouby - I suggest we should add the same test unit on the PR as well. Maybe somewhere in wpInsertTerm.php

Note: See TracTickets for help on using tickets.