diff --git src/wp-includes/class-wp-term-query.php src/wp-includes/class-wp-term-query.php
index 2f3da47301..c4545eda75 100644
--- src/wp-includes/class-wp-term-query.php
+++ src/wp-includes/class-wp-term-query.php
@@ -585,32 +585,17 @@ class WP_Term_Query {
 
 		$selects = array();
 		switch ( $args['fields'] ) {
-			case 'all':
-			case 'all_with_object_id' :
-			case 'tt_ids' :
-			case 'slugs' :
-				$selects = array( 't.*', 'tt.*' );
-				if ( 'all_with_object_id' === $args['fields'] && ! empty( $args['object_ids'] ) ) {
-					$selects[] = 'tr.object_id';
-				}
-				break;
-			case 'ids':
-			case 'id=>parent':
-				$selects = array( 't.term_id', 'tt.parent', 'tt.count', 'tt.taxonomy' );
-				break;
-			case 'names':
-				$selects = array( 't.term_id', 'tt.parent', 'tt.count', 't.name', 'tt.taxonomy' );
-				break;
 			case 'count':
 				$orderby = '';
 				$order = '';
 				$selects = array( 'COUNT(*)' );
 				break;
-			case 'id=>name':
-				$selects = array( 't.term_id', 't.name', 'tt.count', 'tt.taxonomy' );
+			case 'all_with_object_id' :
+				$selects = array( 't.term_id', 'tr.object_id' );
 				break;
-			case 'id=>slug':
-				$selects = array( 't.term_id', 't.slug', 'tt.count', 'tt.taxonomy' );
+
+			default:
+				$selects = array( 't.term_id' );
 				break;
 		}
 
@@ -672,42 +657,57 @@ class WP_Term_Query {
 
 		$this->request = "{$this->sql_clauses['select']} {$this->sql_clauses['from']} {$where} {$this->sql_clauses['orderby']} {$this->sql_clauses['limits']}";
 
-		// $args can be anything. Only use the args defined in defaults to compute the key.
-		$key = md5( serialize( wp_array_slice_assoc( $args, array_keys( $this->query_var_defaults ) ) ) . serialize( $taxonomies ) . $this->request );
+		$key = md5( $this->request );
 		$last_changed = wp_cache_get_last_changed( 'terms' );
 		$cache_key = "get_terms:$key:$last_changed";
+
 		$cache = wp_cache_get( $cache_key, 'terms' );
-		if ( false !== $cache ) {
-			if ( 'all' === $_fields ) {
-				$cache = array_map( 'get_term', $cache );
-			}
 
-			$this->terms = $cache;
-			return $this->terms;
-		}
+		if ( 'count' === $_fields ) {
+			if ( false === $cache ) {
+				$cache = $wpdb->get_var( $this->request );
+				wp_cache_set( $cache_key, $cache, 'terms' );
+			}
 
-		if ( 'count' == $_fields ) {
-			$count = $wpdb->get_var( $this->request );
-			wp_cache_set( $cache_key, $count, 'terms' );
-			return $count;
+			return $cache;
 		}
 
-		$terms = $wpdb->get_results( $this->request );
-		if ( 'all' == $_fields || 'all_with_object_id' === $_fields ) {
-			update_term_cache( $terms );
+		if ( false === $cache ) {
+			$results = $wpdb->get_results( $this->request );
+			$cache = wp_list_pluck( $results, 'term_id' );
+			wp_cache_set( $cache_key, $cache, 'terms' );
 		}
 
-		// Prime termmeta cache.
-		if ( $args['update_term_meta_cache'] ) {
-			$term_ids = wp_list_pluck( $terms, 'term_id' );
-			update_termmeta_cache( $term_ids );
-		}
+		$term_ids = $cache;
 
-		if ( empty( $terms ) ) {
+		if ( empty( $term_ids ) ) {
 			wp_cache_add( $cache_key, array(), 'terms', DAY_IN_SECONDS );
 			return array();
 		}
 
+		// 'ids' requests only need full term objects in certain cases.
+		if ( 'ids' === $_fields && ! $child_of && ( ! $hierarchical || ! $args['hide_empty'] ) ) {
+			$terms = array();
+			foreach ( $term_ids as $term_id ) {
+				$_term = new stdClass;
+				$_term->term_id = $term_id;
+				$terms[] = $_term;
+			}
+
+			if ( $args['update_term_meta_cache'] ) {
+				update_termmeta_cache( $term_ids );
+			}
+		} else {
+			_prime_term_caches( $term_ids, $args['update_term_meta_cache'] );
+			$terms = array_map( 'get_term', $term_ids );
+
+			if ( in_array( 'tr.object_id', $selects ) ) {
+				foreach ( $results as $index => $result ) {
+					$terms[ $index ]->object_id = (int) $result->object_id;
+				}
+			}
+		}
+
 		if ( $child_of ) {
 			foreach ( $taxonomies as $_tax ) {
 				$children = _get_term_hierarchy( $_tax );
@@ -758,7 +758,7 @@ class WP_Term_Query {
 				}
 
 				$_tt_ids[ $term->term_id ] = 1;
-				$_terms[] = $term;
+				$_terms[]                  = $term;
 			}
 
 			$terms = $_terms;
@@ -808,13 +808,8 @@ class WP_Term_Query {
 			}
 		}
 
-		wp_cache_add( $cache_key, $terms, 'terms', DAY_IN_SECONDS );
-
-		if ( 'all' === $_fields || 'all_with_object_id' === $_fields ) {
-			$terms = array_map( 'get_term', $terms );
-		}
-
 		$this->terms = $terms;
+
 		return $this->terms;
 	}
 
diff --git src/wp-includes/class-wp-term.php src/wp-includes/class-wp-term.php
index 8eb87efbe0..63381b6db0 100644
--- src/wp-includes/class-wp-term.php
+++ src/wp-includes/class-wp-term.php
@@ -140,6 +140,8 @@ final class WP_Term {
 				return false;
 			}
 
+			$_term = false;
+
 			// If a taxonomy was specified, find a match.
 			if ( $taxonomy ) {
 				foreach ( $terms as $match ) {
diff --git src/wp-includes/taxonomy.php src/wp-includes/taxonomy.php
index 0c4012242c..e8c3e149f4 100644
--- src/wp-includes/taxonomy.php
+++ src/wp-includes/taxonomy.php
@@ -3003,11 +3003,7 @@ function clean_term_cache($ids, $taxonomy = '', $clean_taxonomy = true) {
 
 	foreach ( $taxonomies as $taxonomy ) {
 		if ( $clean_taxonomy ) {
-			wp_cache_delete('all_ids', $taxonomy);
-			wp_cache_delete('get', $taxonomy);
-			delete_option("{$taxonomy}_children");
-			// Regenerate {$taxonomy}_children
-			_get_term_hierarchy($taxonomy);
+			clean_taxonomy_cache( $taxonomy );
 		}
 
 		/**
@@ -3027,6 +3023,31 @@ function clean_term_cache($ids, $taxonomy = '', $clean_taxonomy = true) {
 }
 
 /**
+ * Clean the caches for a taxonomy.
+ *
+ * @since 4.9.0
+ *
+ * @param string $taxonomy Taxonomy slug.
+ */
+function clean_taxonomy_cache( $taxonomy ) {
+	wp_cache_delete( 'all_ids', $taxonomy );
+	wp_cache_delete( 'get', $taxonomy );
+
+	// Regenerate cached hierarchy.
+	delete_option( "{$taxonomy}_children" );
+	_get_term_hierarchy( $taxonomy );
+
+	/**
+	 * Fires after a taxonomy's caches have been cleaned.
+	 *
+	 * @since 4.9.0
+	 *
+	 * @param string $taxonomy Taxonomy slug.
+	 */
+	do_action( 'clean_term_cache', $taxonomy );
+}
+
+/**
  * Retrieves the taxonomy relationship to the term object id.
  *
  * Upstream functions (like get_the_terms() and is_object_in_term()) are
@@ -3527,19 +3548,27 @@ function _split_shared_term( $term_id, $term_taxonomy_id, $record = true ) {
 				array( 'parent' => $new_term_id ),
 				array( 'term_taxonomy_id' => $child_tt_id )
 			);
-			clean_term_cache( $term_id, $term_taxonomy->taxonomy );
+			clean_term_cache( (int) $child_tt_id, '', false );
 		}
 	} else {
 		// If the term has no children, we must force its taxonomy cache to be rebuilt separately.
-		clean_term_cache( $new_term_id, $term_taxonomy->taxonomy );
+		clean_term_cache( $new_term_id, $term_taxonomy->taxonomy, false );
 	}
 
+	clean_term_cache( $term_id, $term_taxonomy->taxonomy, false );
+
+	/*
+	 * Taxonomy cache clearing is delayed to avoid race conditions that may occur when
+	 * regenerating the taxonomy's hierarchy tree.
+	 */
+	$taxonomies_to_clean = array( $term_taxonomy->taxonomy );
+
 	// Clean the cache for term taxonomies formerly shared with the current term.
-	$shared_term_taxonomies = $wpdb->get_row( $wpdb->prepare( "SELECT taxonomy FROM $wpdb->term_taxonomy WHERE term_id = %d", $term_id ) );
-	if ( $shared_term_taxonomies ) {
-		foreach ( $shared_term_taxonomies as $shared_term_taxonomy ) {
-			clean_term_cache( $term_id, $shared_term_taxonomy );
-		}
+	$shared_term_taxonomies = $wpdb->get_col( $wpdb->prepare( "SELECT taxonomy FROM $wpdb->term_taxonomy WHERE term_id = %d", $term_id ) );
+	$taxonomies_to_clean = array_merge( $taxonomies_to_clean, $shared_term_taxonomies );
+
+	foreach ( $taxonomies_to_clean as $taxonomy_to_clean ) {
+		clean_taxonomy_cache( $taxonomy_to_clean );
 	}
 
 	// Keep a record of term_ids that have been split, keyed by old term_id. See wp_get_split_term().
diff --git tests/phpunit/tests/term/cache.php tests/phpunit/tests/term/cache.php
index fb7a5a84ab..b303bc840a 100644
--- tests/phpunit/tests/term/cache.php
+++ tests/phpunit/tests/term/cache.php
@@ -229,14 +229,12 @@ class Tests_Term_Cache extends WP_UnitTestCase {
 		$term_id = $this->factory->term->create( array( 'slug' => 'burrito', 'name' => 'Taco', 'taxonomy' => 'post_tag' ) );
 
 		clean_term_cache( $term_id, 'post_tag' );
-		$num_queries = $wpdb->num_queries;
 
 		$term = get_term_by( 'slug', 'burrito', 'post_tag' );
-		$num_queries++;
 		$this->assertEquals( 'Taco', $term->name );
-		$this->assertEquals( $num_queries, $wpdb->num_queries );
 
 		// This should now hit cache.
+		$num_queries = $wpdb->num_queries;
 		$term = get_term_by( 'slug', 'burrito', 'post_tag' );
 		$this->assertEquals( 'Taco', $term->name );
 		$this->assertEquals( $num_queries, $wpdb->num_queries );
@@ -254,14 +252,12 @@ class Tests_Term_Cache extends WP_UnitTestCase {
 		$term_id = $this->factory->term->create( array( 'slug' => 'burrito', 'name' => 'Taco', 'taxonomy' => 'post_tag' ) );
 
 		clean_term_cache( $term_id, 'post_tag' );
-		$num_queries = $wpdb->num_queries;
 
 		$term = get_term_by( 'slug', 'burrito', 'post_tag' );
-		$num_queries++;
 		$this->assertEquals( 'Taco', $term->name );
-		$this->assertEquals( $num_queries, $wpdb->num_queries );
 
 		// This should now hit cache.
+		$num_queries = $wpdb->num_queries;
 		$term = get_term_by( 'slug', 'burrito', 'post_tag' );
 		$this->assertEquals( 'Taco', $term->name );
 		$this->assertEquals( $num_queries, $wpdb->num_queries );
@@ -272,9 +268,8 @@ class Tests_Term_Cache extends WP_UnitTestCase {
 
 		// This should not hit cache.
 		$term = get_term_by( 'slug', 'burrito', 'post_tag' );
-		$num_queries++;
 		$this->assertEquals( 'No Taco', $term->name );
-		$this->assertEquals( $num_queries, $wpdb->num_queries );
+		$this->assertGreaterThan( $num_queries, $wpdb->num_queries );
 	}
 
 	/**
@@ -286,13 +281,12 @@ class Tests_Term_Cache extends WP_UnitTestCase {
 		$term_id = $this->factory->term->create( array( 'name' => 'Burrito', 'slug' => 'noburrito', 'taxonomy' => 'post_tag' ) );
 
 		clean_term_cache( $term_id, 'post_tag' );
-		$num_queries = $wpdb->num_queries;
 
-		get_term_by( 'name', 'Burrito', 'post_tag' );
-		$num_queries++;
-		$this->assertEquals( $num_queries, $wpdb->num_queries );
+		$term = get_term_by( 'name', 'Burrito', 'post_tag' );
+		$this->assertSame( 'Burrito', $term->name );
 
 		// This should now hit cache.
+		$num_queries = $wpdb->num_queries;
 		$term = get_term_by( 'name', 'Burrito', 'post_tag' );
 		$this->assertEquals( $num_queries, $wpdb->num_queries );
 
@@ -309,13 +303,11 @@ class Tests_Term_Cache extends WP_UnitTestCase {
 		$term_id = $this->factory->term->create( array( 'name' => 'Burrito', 'slug' => 'noburrito', 'taxonomy' => 'post_tag' ) );
 
 		clean_term_cache( $term_id, 'post_tag' );
-		$num_queries = $wpdb->num_queries;
 
 		get_term_by( 'name', 'Burrito', 'post_tag' );
-		$num_queries++;
-		$this->assertEquals( $num_queries, $wpdb->num_queries );
 
 		// This should now hit cache.
+		$num_queries = $wpdb->num_queries;
 		get_term_by( 'name', 'Burrito', 'post_tag' );
 		$this->assertEquals( $num_queries, $wpdb->num_queries );
 
@@ -325,8 +317,7 @@ class Tests_Term_Cache extends WP_UnitTestCase {
 
 		// This should not hit cache.
 		get_term_by( 'name', 'burrito', 'post_tag' );
-		$num_queries++;
-		$this->assertEquals( $num_queries, $wpdb->num_queries );
+		$this->assertGreaterThan( $num_queries, $wpdb->num_queries );
 	}
 
 	/**
@@ -338,13 +329,12 @@ class Tests_Term_Cache extends WP_UnitTestCase {
 		$term_id = $this->factory->term->create( array( 'name' => 'Burrito', 'taxonomy' => 'post_tag' ) );
 
 		clean_term_cache( $term_id, 'post_tag' );
-		$num_queries = $wpdb->num_queries;
 		$last_changed = wp_cache_get( 'last_changed', 'terms' );
 
 		$term1 = get_term_by( 'name', 'Burrito', 'post_tag' );
-		$num_queries++;
 
 		// Verify the term is cached.
+		$num_queries = $wpdb->num_queries;
 		$term2 = get_term_by( 'name', 'Burrito', 'post_tag' );
 		$this->assertEquals( $num_queries, $wpdb->num_queries );
 		$this->assertEquals( $term1, $term2 );
@@ -377,14 +367,12 @@ class Tests_Term_Cache extends WP_UnitTestCase {
 		add_term_meta( $term_id, 'foo', 'bar' );
 
 		clean_term_cache( $term_id, 'post_tag' );
-		$num_queries = $wpdb->num_queries;
 
 		$term = get_term_by( 'name', 'Burrito', 'post_tag' );
-		$num_queries++;
 		$this->assertTrue( $term instanceof WP_Term );
 		$this->assertSame( $term_id, $term->term_id );
-		$this->assertEquals( $num_queries, $wpdb->num_queries );
 
+		$num_queries = $wpdb->num_queries;
 		$term_meta = get_term_meta( $term_id, 'foo', true );
 		$num_queries++;
 		$this->assertSame( $term_meta, 'bar' );
diff --git tests/phpunit/tests/term/getTermBy.php tests/phpunit/tests/term/getTermBy.php
index 4adda74f5a..ea8c386779 100644
--- tests/phpunit/tests/term/getTermBy.php
+++ tests/phpunit/tests/term/getTermBy.php
@@ -108,15 +108,13 @@ class Tests_Term_GetTermBy extends WP_UnitTestCase {
 
 		clean_term_cache( $t, 'wptests_tax' );
 
-		$num_queries = $wpdb->num_queries;
 		$found = get_term_by( 'slug', 'foo', 'wptests_tax' );
-		$num_queries++;
 
 		$this->assertTrue( $found instanceof WP_Term );
 		$this->assertSame( $t, $found->term_id );
-		$this->assertSame( $num_queries, $wpdb->num_queries );
 
 		// Calls to `get_term()` should now hit cache.
+		$num_queries = $wpdb->num_queries;
 		$found2 = get_term( $t );
 		$this->assertSame( $t, $found->term_id );
 		$this->assertSame( $num_queries, $wpdb->num_queries );
@@ -172,30 +170,6 @@ class Tests_Term_GetTermBy extends WP_UnitTestCase {
 	/**
 	 * @ticket 21760
 	 */
-	public function test_query_should_not_contain_order_by_clause() {
-		global $wpdb;
-
-		$term_id = $this->factory->term->create( array( 'name' => 'burrito', 'taxonomy' => 'post_tag' ) );
-		$found = get_term_by( 'name', 'burrito', 'post_tag' );
-		$this->assertSame( $term_id, $found->term_id );
-		$this->assertNotContains( 'ORDER BY', $wpdb->last_query );
-	}
-
-	/**
-	 * @ticket 21760
-	 */
-	public function test_query_should_contain_limit_clause() {
-		global $wpdb;
-
-		$term_id = $this->factory->term->create( array( 'name' => 'burrito', 'taxonomy' => 'post_tag' ) );
-		$found = get_term_by( 'name', 'burrito', 'post_tag' );
-		$this->assertSame( $term_id, $found->term_id );
-		$this->assertContains( 'LIMIT 1', $wpdb->last_query );
-	}
-
-	/**
-	 * @ticket 21760
-	 */
 	public function test_prevent_recursion_by_get_terms_filter() {
 		$action = new MockAction();
 
diff --git tests/phpunit/tests/term/getTerms.php tests/phpunit/tests/term/getTerms.php
index 575e5ca1c0..01a79faddd 100644
--- tests/phpunit/tests/term/getTerms.php
+++ tests/phpunit/tests/term/getTerms.php
@@ -112,7 +112,7 @@ class Tests_Term_getTerms extends WP_UnitTestCase {
 		$this->assertEquals( 3, count( $terms ) );
 		$time1 = wp_cache_get( 'last_changed', 'terms' );
 		$this->assertNotEmpty( $time1 );
-		$this->assertEquals( $num_queries + 1, $wpdb->num_queries );
+		$this->assertEquals( $num_queries + 2, $wpdb->num_queries );
 
 		$num_queries = $wpdb->num_queries;
 
diff --git tests/phpunit/tests/term/isObjectInTerm.php tests/phpunit/tests/term/isObjectInTerm.php
index ed054f8ea3..5aa55d88a0 100644
--- tests/phpunit/tests/term/isObjectInTerm.php
+++ tests/phpunit/tests/term/isObjectInTerm.php
@@ -113,11 +113,9 @@ class Tests_IsObjectInTerm extends WP_UnitTestCase {
 		$o = 12345;
 		wp_set_object_terms( $o, $terms[0], 'wptests_tax' );
 
-		$num_queries = $wpdb->num_queries;
 		$this->assertTrue( is_object_in_term( $o, 'wptests_tax', $terms[0] ) );
-		$num_queries++;
-		$this->assertSame( $num_queries, $wpdb->num_queries );
 
+		$num_queries = $wpdb->num_queries;
 		$this->assertFalse( is_object_in_term( $o, 'wptests_tax', $terms[1] ) );
 		$this->assertSame( $num_queries, $wpdb->num_queries );
 	}
@@ -134,17 +132,11 @@ class Tests_IsObjectInTerm extends WP_UnitTestCase {
 		$o = 12345;
 		wp_set_object_terms( $o, $terms[0], 'wptests_tax' );
 
-		$num_queries = $wpdb->num_queries;
 		$this->assertTrue( is_object_in_term( $o, 'wptests_tax', $terms[0] ) );
-		$num_queries++;
-		$this->assertSame( $num_queries, $wpdb->num_queries );
 
 		wp_set_object_terms( $o, $terms[1], 'wptests_tax' );
 
-		$num_queries = $wpdb->num_queries;
 		$this->assertTrue( is_object_in_term( $o, 'wptests_tax', $terms[1] ) );
-		$num_queries++;
-		$this->assertSame( $num_queries, $wpdb->num_queries );
 	}
 
 	/**
