@@ -294,12 +294,30 @@ namespace mongo {
294
294
}
295
295
}
296
296
297
+ // If the winning plan produced no results during the ranking period (and, therefore, no
298
+ // plan produced results during the ranking period), then we will not create a plan cache
299
+ // entry.
300
+ if (alreadyProduced.empty () && NULL != _collection) {
301
+ size_t winnerIdx = ranking->candidateOrder [0 ];
302
+ LOG (1 ) << " Winning plan had zero results. Not caching."
303
+ << " ns: " << _collection->ns ()
304
+ << " " << _query->toStringShort ()
305
+ << " winner score: " << ranking->scores [0 ]
306
+ << " winner summary: "
307
+ << Explain::getPlanSummary (_candidates[winnerIdx].root );
308
+ }
309
+
297
310
// Store the choice we just made in the cache. In order to do so,
298
- // 1) the query must be of a type that is safe to cache, and
299
- // 2) two or more plans cannot have tied for the win. Caching in the
300
- // case of ties can cause successive queries of the same shape to
301
- // use a bad index.
302
- if (PlanCache::shouldCacheQuery (*_query) && !ranking->tieForBest ) {
311
+ // 1) the query must be of a type that is safe to cache,
312
+ // 2) two or more plans cannot have tied for the win. Caching in the case of ties can
313
+ // cause successive queries of the same shape to use a bad index.
314
+ // 3) Furthermore, the winning plan must have returned at least one result. Plans which
315
+ // return zero results cannot be reliably ranked. Such query shapes are generally
316
+ // existence type queries, and a winning plan should get cached once the query finds a
317
+ // result.
318
+ if (PlanCache::shouldCacheQuery (*_query)
319
+ && !ranking->tieForBest
320
+ && !alreadyProduced.empty ()) {
303
321
// Create list of candidate solutions for the cache with
304
322
// the best solution at the front.
305
323
std::vector<QuerySolution*> solutions;
0 commit comments