Index: wp-includes/post.php
===================================================================
--- wp-includes/post.php	(revision 22244)
+++ wp-includes/post.php	(working copy)
@@ -2224,7 +2224,7 @@
 
 	if ( is_post_type_hierarchical( $post->post_type ) && $children ) {
 		foreach ( $children as $child )
-			clean_post_cache( $child );
+			clean_post_cache( $child, 'delete_parent' );
 	}
 
 	wp_clear_scheduled_hook('publish_future_post', array( $postid ) );
@@ -4480,8 +4480,9 @@
  * @uses do_action() Calls 'clean_post_cache' on $id before adding children (if any).
  *
  * @param object|int $post The post object or ID to remove from the cache
+ * @param string $context The context in which clean_post_cache() is called. Default is empty string.
  */
-function clean_post_cache( $post ) {
+function clean_post_cache( $post, $context = '' ) {
 	global $_wp_suspend_cache_invalidation, $wpdb;
 
 	if ( ! empty( $_wp_suspend_cache_invalidation ) )
@@ -4498,7 +4499,7 @@
 
 	wp_cache_delete( 'wp_get_archives', 'general' );
 
-	do_action( 'clean_post_cache', $post->ID, $post );
+	do_action( 'clean_post_cache', $post->ID, $post, $context );
 
 	if ( is_post_type_hierarchical( $post->post_type ) )
 		wp_cache_delete( 'get_pages', 'posts' );
@@ -4507,6 +4508,18 @@
 		wp_cache_delete( 'all_page_ids', 'posts' );
 		do_action( 'clean_page_cache', $post->ID );
 	}
+
+	// Increment last_changed to invalidate query caches except for contexts
+	// where clean_post_cache() has already been called for this page load
+	// and contexts which do not affect query results.
+	if ( ! ( 'delete_parent' == $context || 'update_comment_count' == $context ) ) {
+		if ( function_exists( 'wp_cache_incr' ) ) {
+			wp_cache_incr( 'last_changed', 1, 'posts' );
+		} else {
+			$last_changed = wp_cache_get( 'last_changed', 'posts' );
+			wp_cache_set( 'last_changed', $last_changed + 1, 'posts' );
+		}
+	}
 }
 
 /**
Index: wp-includes/comment.php
===================================================================
--- wp-includes/comment.php	(revision 22244)
+++ wp-includes/comment.php	(working copy)
@@ -1618,7 +1618,7 @@
 	$new = (int) $wpdb->get_var( $wpdb->prepare("SELECT COUNT(*) FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_approved = '1'", $post_id) );
 	$wpdb->update( $wpdb->posts, array('comment_count' => $new), array('ID' => $post_id) );
 
-	clean_post_cache( $post );
+	clean_post_cache( $post, 'update_comment_count' );
 
 	do_action('wp_update_comment_count', $post_id, $new, $old);
 	do_action('edit_post', $post_id, $post);
Index: wp-includes/query.php
===================================================================
--- wp-includes/query.php	(revision 22244)
+++ wp-includes/query.php	(working copy)
@@ -1279,6 +1279,15 @@
 	 */
 	 var $thumbnails_cached = false;
 
+	 /**
+	  * The cache key for the posts_request_ids query cache.
+	  *
+	  * @since 3.6.0
+	  * @access private
+	  * @var string
+	  */
+	 private $cache_key;
+
 	/**
 	 * Resets query flags to false.
 	 *
@@ -2661,8 +2670,16 @@
 
 			$this->request = apply_filters( 'posts_request_ids', $this->request, $this );
 
-			$ids = $wpdb->get_col( $this->request );
+			$last_changed = wp_cache_get( 'last_changed', 'posts' );
+			if ( ! $last_changed )
+				$last_changed = wp_cache_set( 'last_changed', 1, 'posts' );
+			$this->cache_key = md5( $this->request ) . $last_changed;
 
+			if ( ! $ids = wp_cache_get( $this->cache_key, 'posts' ) ) {
+				$ids = $wpdb->get_col( $this->request );
+				wp_cache_set( $this->cache_key, $ids, 'posts' );
+			}
+
 			if ( $ids ) {
 				$this->posts = $ids;
 				$this->set_found_posts( $q, $limits );
@@ -2802,13 +2819,19 @@
 		if ( $q['no_found_rows'] || ! $this->posts )
 			return;
 
-		if ( ! empty( $limits ) )
-			$this->found_posts = $wpdb->get_var( apply_filters_ref_array( 'found_posts_query', array( 'SELECT FOUND_ROWS()', &$this ) ) );
-		else
-			$this->found_posts = count( $this->posts );
+		if ( ! $this->cache_key || ! $this->found_posts = wp_cache_get( $this->cache_key . '_found', 'posts' ) ) {
+			if ( ! empty( $limits ) )
+				$this->found_posts = $wpdb->get_var( apply_filters_ref_array( 'found_posts_query', array( 'SELECT FOUND_ROWS()', &$this ) ) );
+			else
+				$this->found_posts = count( $this->posts );
 
-		$this->found_posts = apply_filters_ref_array( 'found_posts', array( $this->found_posts, &$this ) );
+			$this->found_posts = apply_filters_ref_array( 'found_posts', array( $this->found_posts, &$this ) );
 
+			wp_cache_set( $this->cache_key . '_found', $this->found_posts, 'posts' );
+		} else {
+			$this->found_posts = apply_filters_ref_array( 'found_posts', array( $this->found_posts, &$this ) );
+		}
+
 		if ( ! empty( $limits ) )
 			$this->max_num_pages = ceil( $this->found_posts / $q['posts_per_page'] );
 	}
