summaryrefslogtreecommitdiff
path: root/jstests/core/plan_cache_list_plans.js
diff options
context:
space:
mode:
authorjannaerin <golden.janna@gmail.com>2017-10-27 12:53:48 -0400
committerjannaerin <golden.janna@gmail.com>2017-11-13 18:21:23 -0500
commitbace2a3017ebd46ca96cc81f48f039b80e00d92a (patch)
tree591bfb62702350ecff78bb6d48bf333a849fc9fe /jstests/core/plan_cache_list_plans.js
parent956a2d030f04e5bbb2213ac6052f10d82cd3ec74 (diff)
downloadmongo-bace2a3017ebd46ca96cc81f48f039b80e00d92a.tar.gz
SERVER-31610 Add timestamp to plan cache entries
Diffstat (limited to 'jstests/core/plan_cache_list_plans.js')
-rw-r--r--jstests/core/plan_cache_list_plans.js170
1 files changed, 98 insertions, 72 deletions
diff --git a/jstests/core/plan_cache_list_plans.js b/jstests/core/plan_cache_list_plans.js
index 7ca599483ff..4da32686ae6 100644
--- a/jstests/core/plan_cache_list_plans.js
+++ b/jstests/core/plan_cache_list_plans.js
@@ -1,75 +1,101 @@
// 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');
+(function() {
+ "use strict";
+ let t = db.jstests_plan_cache_list_plans;
+ t.drop();
+
+ // Utility function to list plans for a query.
+ function getPlans(query, sort, projection) {
+ let key = {query: query, sort: sort, projection: projection};
+ let 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;
+ }
+
+ // Assert that timeOfCreation exists in the cache entry. The difference between the current time
+ // and
+ // the time a plan was cached should not be larger than an hour.
+ function checkTimeOfCreation(query, sort, projection, date) {
+ let key = {query: query, sort: sort, projection: projection};
+ let res = t.runCommand('planCacheListPlans', key);
+ assert.commandWorked(res, 'planCacheListPlans(' + tojson(key, '', true) + ' failed');
+ assert(res.hasOwnProperty('timeOfCreation'),
+ 'timeOfCreation missing from planCacheListPlans');
+ let kMillisecondsPerHour = 1000 * 60 * 60;
+ assert.lte(Math.abs(date - res.timeOfCreation.getTime()),
+ kMillisecondsPerHour,
+ 'timeOfCreation value is incorrect');
+ }
+
+ 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');
+
+ let now = (new Date()).getTime();
+ checkTimeOfCreation({a: 1, b: 1}, {a: -1}, {_id: 0, a: 1}, now);
+
+ // Retrieve plans for valid cache entry.
+ let 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 (let 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.
+ let numExecutions = 100;
+ for (let i = 0; i < numExecutions; i++) {
+ assert.eq(0, t.find({a: 3, b: 3}, {_id: 0, a: 1}).sort({a: -1}).itcount(), 'query failed');
+ }
+
+ now = (new Date()).getTime();
+ checkTimeOfCreation({a: 3, b: 3}, {a: -1}, {_id: 0, a: 1}, now);
+
+ 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 (let 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('stage'), 'no stats inserted for plan ' + i);
}
- assert(plans[i].reason.stats.hasOwnProperty('stage'), 'no stats inserted for plan ' + i);
-}
+})();