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

Explode for sort caches incorrect parameterized plans

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Major - P3 Major - P3
    • 6.1.0-rc0
    • Affects Version/s: 6.0.0-rc5, 6.1.0-rc0
    • Component/s: None
    • Labels:
      None
    • Fully Compatible
    • ALL
    • v6.0
    • Hide

      The second assertion in this repro script fails against a server that has SBE and the SBE plan cache enabled:

      (function() {
      "use strict";
      
      const coll = db.c;
      coll.drop();
      
      assert.commandWorked(coll.createIndex({a: 1, b: 1, c: 1}));
      assert.commandWorked(coll.insert({a: 2, b: 3}));
      
      // Create an SBE plan cache.
      assert.eq(0, coll.find({a: {$eq: 2}, b: {$in: [99, 4]}}).sort({c: 1}).itcount());
      
      // Run a query that reuses the cache entry and should return the one document in the collection.
      assert.eq(1, coll.find({a: {$eq: 2}, b: {$in: [3, 4]}}).sort({c: 1}).itcount());
      }());
      
      Show
      The second assertion in this repro script fails against a server that has SBE and the SBE plan cache enabled: (function() { "use strict"; const coll = db.c; coll.drop(); assert.commandWorked(coll.createIndex({a: 1, b: 1, c: 1})); assert.commandWorked(coll.insert({a: 2, b: 3})); // Create an SBE plan cache. assert.eq(0, coll.find({a: {$eq: 2}, b: {$in: [99, 4]}}).sort({c: 1}).itcount()); // Run a query that reuses the cache entry and should return the one document in the collection. assert.eq(1, coll.find({a: {$eq: 2}, b: {$in: [3, 4]}}).sort({c: 1}).itcount()); }());
    • QO 2022-05-16, QO 2022-05-30, QO 2022-06-13, QO 2022-06-27, QO 2022-07-11

      The QueryPlanner has some special logic called "explode for sort" which attempts to convert one index scan into a sorted merge of several index scans in order to avoid a blocking SORT operation. This logic does not interact correctly with auto-parameterization.

      When an auto-parameterized predicate is converted to index bounds in the IndexBoundsBuilder, we record this fact inside an IntervalEvaluationTree, or IET. The IET allows us to recompute the index bounds when the indexed plan is bound to new parameter values. The explode for sort path appears to discard the IETs attached to the original IndexScanNode. This results in the downstream logic treating the index scan as though it is not parameterized, embedding the KeyString constants for the high and low keys directly into the plan. When the plan is recovered from the cache for a query with different constants, this can result in incorrect or missing query results.

            Assignee:
            anton.korshunov@mongodb.com Anton Korshunov
            Reporter:
            david.storch@mongodb.com David Storch
            Votes:
            0 Vote for this issue
            Watchers:
            12 Start watching this issue

              Created:
              Updated:
              Resolved: