Index: src/wp-includes/class-wp-query.php
===================================================================
--- src/wp-includes/class-wp-query.php	(revision 42039)
+++ src/wp-includes/class-wp-query.php	(working copy)
@@ -968,6 +968,7 @@
 			}
 		}
 
+
 		if ( !empty($qv['post_type']) ) {
 			if ( is_array($qv['post_type']) )
 				$qv['post_type'] = array_map('sanitize_key', $qv['post_type']);
@@ -2257,7 +2258,6 @@
 			$where .= " AND {$wpdb->posts}.post_type = 'post'";
 			$post_type_object = get_post_type_object ( 'post' );
 		}
-
 		$edit_cap = 'edit_post';
 		$read_cap = 'read_post';
 
Index: src/wp-includes/class-wp-site-query.php
===================================================================
--- src/wp-includes/class-wp-site-query.php	(revision 42039)
+++ src/wp-includes/class-wp-site-query.php	(working copy)
@@ -240,16 +240,8 @@
 		 */
 		do_action_ref_array( 'pre_get_sites', array( &$this ) );
 
-		// $args can include anything. Only use the args defined in the query_var_defaults to compute the key.
-		$_args = wp_array_slice_assoc( $this->query_vars, array_keys( $this->query_var_defaults ) );
-
-		// Ignore the $fields argument as the queried result will be the same regardless.
-		unset( $_args['fields'] );
+		$cache_key = $this->get_cache_key( $this->query_vars );
 
-		$key = md5( serialize( $_args ) );
-		$last_changed = wp_cache_get_last_changed( 'sites' );
-
-		$cache_key = "get_sites:$key:$last_changed";
 		$cache_value = wp_cache_get( $cache_key, 'sites' );
 
 		if ( false === $cache_value ) {
@@ -698,4 +690,64 @@
 			return 'DESC';
 		}
 	}
+
+	/**
+	 * Generates the cache key to lookup query results for a specific set of arguments.
+	 *
+	 * @since 5.0.0
+	 *
+	 * @param array $query_vars Array of WP_Site_Query arguments. See WP_Site_Query::__construct().
+	 * @return string Cache key to use for the lookup.
+	 */
+	protected function get_cache_key( $query_vars ) {
+		// $args can include anything. Only use the args defined in the query_var_defaults to compute the key.
+		$_args = wp_array_slice_assoc( $query_vars, array_keys( $this->query_var_defaults ) );
+
+		// Ignore the $fields argument as the queried result will be the same regardless.
+		unset( $_args['fields'] );
+
+		// Ignore the $update_site_cache as it does not affect the query.
+		unset( $_args['update_site_cache'] );
+
+		// Use the same cache key for array lookups with one element and single value lookups.
+		$single_multi_mappings = array(
+			'ID'         => 'site__in',
+			'network_id' => 'network__in',
+			'domain'     => 'domain__in',
+			'path'       => 'path__in',
+			'lang_id'    => 'lang__in',
+		);
+		foreach ( $single_multi_mappings as $single_var => $multi_var ) {
+			if ( empty( $_args[ $single_var ] ) && isset( $_args[ $multi_var ] ) && is_array( $_args[ $multi_var ] ) && count( $_args[ $multi_var ] ) === 1 ) {
+				$_args[ $single_var ] = array_pop( $_args[ $multi_var ] );
+				$_args[ $multi_var ]  = '';
+			}
+		}
+
+		$key                 = md5( serialize( $_args ) );
+		$used_args           = array_filter( $_args );
+		$params              = array( 'domain', 'path', 'network_id' );
+		$array_keys          = array_intersect( $params, array_keys( $used_args ) );
+		$last_changed_prefix = array();
+		$counter             = count( $array_keys );
+		if ( $counter > 0 ) {
+			foreach ( $params as $param ) {
+				if ( ! isset( $used_args[ $param ] ) || empty( $used_args[ $param ] ) ) {
+					if ( $counter > 1 ) {
+						break;
+					}
+					continue;
+				}
+				$last_changed_prefix[$param] = $used_args[ $param ];
+			}
+		}
+		$last_changed_key = 'last_changed';
+		if ( $last_changed_prefix ) {
+			$last_changed_prefix = md5( serialize( $last_changed_prefix ) );
+			$last_changed_key    = $last_changed_prefix . '_last_changed';
+		}
+		$last_changed = wp_cache_get_last_changed( 'sites', $last_changed_key );
+
+		return "get_sites:$key:$last_changed";
+	}
 }
Index: src/wp-includes/functions.php
===================================================================
--- src/wp-includes/functions.php	(revision 42039)
+++ src/wp-includes/functions.php	(working copy)
@@ -5710,17 +5710,22 @@
  * Get last changed date for the specified cache group.
  *
  * @since 4.7.0
+ * @since 5.0.0 Now supports the $prefix parameter.
  *
- * @param string $group Where the cache contents are grouped.
+ * @param string $group  Where the cache contents are grouped.
+ * @param string $key Optional. Key to look for a specific last changed key. Default empty string.
  *
  * @return string $last_changed UNIX timestamp with microseconds representing when the group was last changed.
  */
-function wp_cache_get_last_changed( $group ) {
-	$last_changed = wp_cache_get( 'last_changed', $group );
+function wp_cache_get_last_changed( $group, $key = '' ) {
+	if ( empty( $key ) ) {
+		$key = 'last_changed';
+	}
+	$last_changed = wp_cache_get( $key, $group );
 
 	if ( ! $last_changed ) {
 		$last_changed = microtime();
-		wp_cache_set( 'last_changed', $last_changed, $group );
+		wp_cache_set( $key, $last_changed, $group );
 	}
 
 	return $last_changed;
Index: src/wp-includes/ms-blogs.php
===================================================================
--- src/wp-includes/ms-blogs.php	(revision 42039)
+++ src/wp-includes/ms-blogs.php	(working copy)
@@ -447,6 +447,7 @@
 			'blog_id' => $blog_id,
 			'domain'  => null,
 			'path'    => null,
+			'site_id' => get_current_network_id(),
 		) );
 	}
 
@@ -473,7 +474,22 @@
 	 */
 	do_action( 'clean_site_cache', $blog_id, $blog, $domain_path_key );
 
-	wp_cache_set( 'last_changed', microtime(), 'sites' );
+	$current_time = microtime();
+
+	$last_changed_keys   = array( 'last_changed' );
+	$params              = array( 'domain', 'path', 'site_id' );
+	$last_changed_prefix = array();
+	foreach ( $params as $param ) {
+		$last_changed_keys[]           = md5( serialize( array( $param => $blog->$param ) ) ) . '_last_changed';
+		$last_changed_prefix[ $param ] = $blog->$param;
+		$key                           = md5( serialize( $last_changed_prefix ) );
+		$last_changed_keys[]           = $key . '_last_changed';
+	}
+
+	$last_changed_keys = array_unique( $last_changed_keys );
+	foreach ( $last_changed_keys as $last_changed_key ) {
+		wp_cache_set( $last_changed_key, $current_time, 'sites' );
+	}
 
 	/**
 	 * Fires after the blog details cache is cleared.
