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

Cached SBE plans have let-bound constants baked in

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Major - P3 Major - P3
    • 7.3.0-rc4, 7.0.9, 7.3.2, 6.0.17
    • Affects Version/s: None
    • Component/s: None
    • None
    • Query Optimization
    • Fully Compatible
    • ALL
    • v7.3, v7.2, v7.0, v6.0
    • 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, QO 2024-03-04

      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.

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

              Created:
              Updated:
              Resolved: