Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-15924

planCacheListPlans command can report incorrect averageScore and stdDevScore in "feedback" section

    • Type: Icon: Bug Bug
    • Resolution: Done
    • Priority: Icon: Minor - P4 Minor - P4
    • None
    • Affects Version/s: 2.6.5, 2.7.8
    • Component/s: Querying
    • None
    • ALL
    • Hide
      > t.drop();
      > for (var i = 0; i < 20; i++) { t.insert({_id: i, a: i, b: 1}); }
      > t.ensureIndex({a: 1});
      > t.ensureIndex({b: 1});
      
      // Run a query twice. The first run causes a plan to be cached. The second
      // adds a feedback entry.
      > t.find({a: {$lt: 3}, b: 1}).next()
      > t.find({a: {$lt: 3}, b: 1}).next()
      
      // Get the plan cache entry.
      > t.getPlanCache().getPlansByQuery({a: {$lt: 3}, b: 1})
      [
         ...
      		"feedback" : {
      			"nfeedback" : 1,
      			"averageScore" : 0, // XXX: incorrect!
      			"stdDevScore" : 0, // XXX: incorrect!
      			"scores" : [
      				{
      					"score" : 1.7503
      				}
      			]
      		},
      		"filterSet" : false
      	},
         ...
      ]
      
      // After running the query a few more times, the average and std dev are computed.
      > for (var i = 0; i < 20; i++) { t.find({a: {$lt: 3}, b: 1}).next(); }
      > t.getPlanCache().getPlansByQuery({a: {$lt: 3}, b: 1})
      [
         ...
      		"feedback" : {
      			"nfeedback" : 20,
      			"averageScore" : 1.7502999999999997,
      			"stdDevScore" : 2.278129578503827e-16,
      			"scores" : [
      				{
      					"score" : 1.7503
      				},
      				{
      					"score" : 1.7503
      				},
      				{
      					"score" : 1.7503
      				},
      				{
      					"score" : 1.7503
      				},
      				{
      					"score" : 1.7503
      				},
      				{
      					"score" : 1.7503
      				},
      				{
      					"score" : 1.7503
      				},
      				{
      					"score" : 1.7503
      				},
      				{
      					"score" : 1.7503
      				},
      				{
      					"score" : 1.7503
      				},
      				{
      					"score" : 1.7503
      				},
      				{
      					"score" : 1.7503
      				},
      				{
      					"score" : 1.7503
      				},
      				{
      					"score" : 1.7503
      				},
      				{
      					"score" : 1.7503
      				},
      				{
      					"score" : 1.7503
      				},
      				{
      					"score" : 1.7503
      				},
      				{
      					"score" : 1.7503
      				},
      				{
      					"score" : 1.7503
      				},
      				{
      					"score" : 1.7503
      				}
      			]
      		},
         ...
      ]
      
      Show
      > t.drop(); > for ( var i = 0; i < 20; i++) { t.insert({_id: i, a: i, b: 1}); } > t.ensureIndex({a: 1}); > t.ensureIndex({b: 1}); // Run a query twice. The first run causes a plan to be cached. The second // adds a feedback entry. > t.find({a: {$lt: 3}, b: 1}).next() > t.find({a: {$lt: 3}, b: 1}).next() // Get the plan cache entry. > t.getPlanCache().getPlansByQuery({a: {$lt: 3}, b: 1}) [ ... "feedback" : { "nfeedback" : 1, "averageScore" : 0, // XXX: incorrect! "stdDevScore" : 0, // XXX: incorrect! "scores" : [ { "score" : 1.7503 } ] }, "filterSet" : false }, ... ] // After running the query a few more times, the average and std dev are computed. > for ( var i = 0; i < 20; i++) { t.find({a: {$lt: 3}, b: 1}).next(); } > t.getPlanCache().getPlansByQuery({a: {$lt: 3}, b: 1}) [ ... "feedback" : { "nfeedback" : 20, "averageScore" : 1.7502999999999997, "stdDevScore" : 2.278129578503827e-16, "scores" : [ { "score" : 1.7503 }, { "score" : 1.7503 }, { "score" : 1.7503 }, { "score" : 1.7503 }, { "score" : 1.7503 }, { "score" : 1.7503 }, { "score" : 1.7503 }, { "score" : 1.7503 }, { "score" : 1.7503 }, { "score" : 1.7503 }, { "score" : 1.7503 }, { "score" : 1.7503 }, { "score" : 1.7503 }, { "score" : 1.7503 }, { "score" : 1.7503 }, { "score" : 1.7503 }, { "score" : 1.7503 }, { "score" : 1.7503 }, { "score" : 1.7503 }, { "score" : 1.7503 } ] }, ... ]

      The planCacheListPlans command, also exposed via the getPlansByQuery shell helper displays the plan that has been cached for a particular query shape. Each time that a cached plan is reused for another instance of the query shape, stats about the performance of the query are tracked. These stats are used to update the "feedback" section of the planCacheListPlans output. This section shows how many times the cached plan was used, as well as the scores for each use of the plan.

      The "averageScore" and "stdDevScore" fields are statistics taken over the history of scores for each run of the cached plan. These statistics are first computed once the plan has been used some small number of times, n. (Currently n defaults to 20.) The list plans command, however, reports the average and standard deviation as 0 even before these values have been computed. See "Steps to Reproduce" for details.

            Assignee:
            david.storch@mongodb.com David Storch
            Reporter:
            david.storch@mongodb.com David Storch
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: