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

Cached SBE plans have let-bound constants baked in

    XMLWordPrintableJSON

Details

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: Major - P3 Major - P3
    • None
    • None
    • None
    • None
    • Query Optimization
    • ALL
    • Hide

      const coll = db.example;
      coll.drop();
      assert.commandWorked(coll.insert({}));
       
      let result;
       
      result = assert
                   .commandWorked(db.runCommand({
                       find: coll.getName(),
                       filter: {},
                       projection: {_id: "$$a"},
                       limit: 1,
                       let : {a: {$add: [2, 3]}},
                   }))
                   .cursor.firstBatch;
      assert.eq(result, [{_id: 5}]);
       
      jsTestLog('plan cache contents');
      printjson(coll.getPlanCache().list());
       
      result = assert
                   .commandWorked(db.runCommand({
                       find: coll.getName(),
                       filter: {},
                       projection: {_id: "$$a"},
                       limit: 1,
                       let : {a: {$add: [200, 300]}},
                   }))
                   .cursor.firstBatch;
      assert.eq(result, [{_id: 500}]);
      

      Show
      const coll = db.example; coll.drop(); assert.commandWorked(coll.insert({}));   let result;   result = assert .commandWorked(db.runCommand({ find: coll.getName(), filter: {}, projection: {_id: "$$a"}, limit: 1, let : {a: {$add: [2, 3]}}, })) .cursor.firstBatch; assert.eq(result, [{_id: 5}]);   jsTestLog('plan cache contents'); printjson(coll.getPlanCache().list());   result = assert .commandWorked(db.runCommand({ find: coll.getName(), filter: {}, projection: {_id: "$$a"}, limit: 1, let : {a: {$add: [200, 300]}}, })) .cursor.firstBatch; assert.eq(result, [{_id: 500}]);
    • QO 2024-02-05, QO 2024-02-19

    Description

      If you run two queries with the same filter, sort, and projection, they map to the same plan cache key. This happens even when they have different top-level let bindings.

      The attached script fails on the default configuration (trySbeEngine). Printing the plan cache in between the two queries shows that the constant 5 is baked in to the plan:

      [3] limit 1 
      [2] project [s3 = makeBsonObj(MakeObjSpec(["_id" = Arg(0)], Closed), s1, 5L)] 
      [1] scan s1 s2 none none none none none none [] @"97a0d744-17cb-4332-aee5-2f196db32553" true false 
      

      Running with forceClassicEngine, the test passes, so this is specific to the SBE stagebuilders plan cache.

      Attachments

        Activity

          People

            ruoxin.xu@mongodb.com Ruoxin Xu
            david.percy@mongodb.com David Percy
            Votes:
            0 Vote for this issue
            Watchers:
            8 Start watching this issue

            Dates

              Created:
              Updated: