summaryrefslogtreecommitdiff
path: root/jstests/core/plan_cache_list_plans.js
diff options
context:
space:
mode:
authorDan Pasette <dan@10gen.com>2014-05-24 19:59:19 -0400
committerDan Pasette <dan@mongodb.com>2014-05-24 19:59:19 -0400
commit213700b3af4d53ce7e808dce2c638d98fc4f91db (patch)
tree3c543d57796174a2eea62f5ba2275ca302bc3fe5 /jstests/core/plan_cache_list_plans.js
parent87fd9929f9cdc0a287db4603704ff69218a8465c (diff)
downloadmongo-213700b3af4d53ce7e808dce2c638d98fc4f91db.tar.gz
SERVER-13675 do not cache plans if there is a tie
(backport of 7dcbdc440a56fef19a561f513d8eddd1c2a2b27f)
Diffstat (limited to 'jstests/core/plan_cache_list_plans.js')
-rw-r--r--jstests/core/plan_cache_list_plans.js74
1 files changed, 74 insertions, 0 deletions
diff --git a/jstests/core/plan_cache_list_plans.js b/jstests/core/plan_cache_list_plans.js
new file mode 100644
index 00000000000..4e90531da25
--- /dev/null
+++ b/jstests/core/plan_cache_list_plans.js
@@ -0,0 +1,74 @@
+// Test the planCacheListPlans command.
+
+var t = db.jstests_plan_cache_list_plans;
+t.drop();
+
+// Utility function to list plans for a query.
+function getPlans(query, sort, projection) {
+ var key = {query: query, sort: sort, projection: projection};
+ var res = t.runCommand('planCacheListPlans', key);
+ assert.commandWorked(res, 'planCacheListPlans(' + tojson(key, '', true) + ' failed');
+ assert(res.hasOwnProperty('plans'), 'plans missing from planCacheListPlans(' +
+ tojson(key, '', true) + ') result');
+ return res.plans;
+}
+
+t.save({a: 1, b: 1});
+t.save({a: 1, b: 2});
+t.save({a: 1, b: 2});
+t.save({a: 2, b: 2});
+
+// We need two indices so that the MultiPlanRunner is executed.
+t.ensureIndex({a: 1});
+t.ensureIndex({a: 1, b:1});
+
+// Invalid key should be an error.
+assert.eq(0, getPlans({unknownfield: 1}, {}, {}),
+ 'planCacheListPlans should return empty results on unknown query shape');
+
+// Create a cache entry.
+assert.eq(1, t.find({a: 1, b: 1}, {_id: 0, a: 1}).sort({a: -1}).itcount(),
+ 'unexpected document count');
+
+// Retrieve plans for valid cache entry.
+var plans = getPlans({a: 1, b: 1}, {a: -1}, {_id: 0, a: 1});
+assert.eq(2, plans.length, 'unexpected number of plans cached for query');
+
+// Print every plan
+// Plan details/feedback verified separately in section after Query Plan Revision tests.
+print('planCacheListPlans result:');
+for (var i = 0; i < plans.length; i++) {
+ print('plan ' + i + ': ' + tojson(plans[i]));
+}
+
+//
+// Tests for plan reason and feedback in planCacheListPlans
+//
+
+// Generate more plans for test query by adding indexes (compound and sparse).
+// This will also clear the plan cache.
+t.ensureIndex({a: -1}, {sparse: true});
+t.ensureIndex({a: 1, b: 1});
+
+// Implementation note: feedback stats is calculated after 20 executions.
+// See PlanCacheEntry::kMaxFeedback.
+var numExecutions = 100;
+for (var i = 0; i < numExecutions; i++) {
+ assert.eq(0, t.find({a: 3, b: 3}, {_id: 0, a: 1}).sort({a: -1}).itcount(), 'query failed');
+}
+
+plans = getPlans({a: 3, b: 3}, {a: -1}, {_id: 0, a: 1});
+
+// This should be obvious but feedback is available only for the first (winning) plan.
+print('planCacheListPlans result (after adding indexes and completing 20 executions):');
+for (var i = 0; i < plans.length; i++) {
+ print('plan ' + i + ': ' + tojson(plans[i]));
+ assert.gt(plans[i].reason.score, 0, 'plan ' + i + ' score is invalid');
+ if (i > 0) {
+ assert.lte(plans[i].reason.score, plans[i-1].reason.score,
+ 'plans not sorted by score in descending order. ' +
+ 'plan ' + i + ' has a score that is greater than that of the previous plan');
+ }
+ assert(plans[i].reason.stats.hasOwnProperty('type'), 'no stats inserted for plan ' + i);
+}
+