Distinct scan doesn't work well with a gapped ChunkMap

XMLWordPrintableJSON

    • Catalog and Routing
    • ALL
    • Hide
      /**
       * @tags: [
       *   featureFlagAuthoritativeShardsDDL,
       * ]
       */
      import {ShardingTest} from "jstests/libs/shardingtest.js";
      
      // The collection deliberately contains an orphan document.
      TestData.xipCheckOrphans = true;
      
      const st = new ShardingTest({shards: 2});
      const dbName = "test";
      const coll = st.s.getDB(dbName).distinct_gapped;
      const ns = coll.getFullName();
      
      // Shard a collection:
      //    - dbPrimary: shard0
      //    - shardkey: {x:1}
      //    - doc inserted: {x:15}
      assert.commandWorked(
          st.s.adminCommand({enableSharding: dbName, primaryShard: st.shard0.shardName}));
      assert.commandWorked(st.s.adminCommand({shardCollection: ns, key: {x: 1}}));
      assert.commandWorked(coll.insert({x: 15}));
      
      // Move range [10, 20) to shard1
      assert.commandWorked(st.s.adminCommand({moveRange: ns, min: {x: 10}, max: {x: 20}, toShard: st.shard1.shardName}));
      
      // Insert an orphan to shard1 lower than {x:15} (the previously inserted doc)
      assert.commandWorked(st.shard1.getCollection(ns).insert({x: 5}));
      
      // Guard that we are actually exercising the shard-filtering DISTINCT_SCAN path.
      assert(JSON.stringify(coll.explain().distinct("x")).includes("DISTINCT_SCAN"),
             "expected a DISTINCT_SCAN plan");
      
      // Distinct doesn't return {x:15} because the DISTINCT_SCAN incorrectly stops when hits the orphan {x:5}
      const res = coll.distinct("x");
      jsTestLog("Distinct result: " + tojson(res));
      assert.eq([15], res);
      
      st.stop();
      
      Show
      /** * @tags: [ * featureFlagAuthoritativeShardsDDL, * ] */ import {ShardingTest} from "jstests/libs/shardingtest.js" ; // The collection deliberately contains an orphan document. TestData.xipCheckOrphans = true ; const st = new ShardingTest({shards: 2}); const dbName = "test" ; const coll = st.s.getDB(dbName).distinct_gapped; const ns = coll.getFullName(); // Shard a collection: // - dbPrimary: shard0 // - shardkey: {x:1} // - doc inserted: {x:15} assert .commandWorked( st.s.adminCommand({enableSharding: dbName, primaryShard: st.shard0.shardName})); assert .commandWorked(st.s.adminCommand({shardCollection: ns, key: {x: 1}})); assert .commandWorked(coll.insert({x: 15})); // Move range [10, 20) to shard1 assert .commandWorked(st.s.adminCommand({moveRange: ns, min: {x: 10}, max: {x: 20}, toShard: st.shard1.shardName})); // Insert an orphan to shard1 lower than {x:15} (the previously inserted doc) assert .commandWorked(st.shard1.getCollection(ns).insert({x: 5})); // Guard that we are actually exercising the shard-filtering DISTINCT_SCAN path. assert (JSON.stringify(coll.explain().distinct( "x" )).includes( "DISTINCT_SCAN" ), "expected a DISTINCT_SCAN plan" ); // Distinct doesn't return {x:15} because the DISTINCT_SCAN incorrectly stops when hits the orphan {x:5} const res = coll.distinct( "x" ); jsTestLog( "Distinct result: " + tojson(res)); assert .eq([15], res); st.stop();
    • CAR Team 2026-07-06
    • None
    • None
    • None
    • None
    • None
    • None
    • None

      When a DISTINCT_SCAN finds an orphan document that is not part of the ChunkMap stops the scan and the succeeding documents are skipped from the scan.

      We don't see failures right now because the ChunkMap always contain all the orphaned chunks. But this may start being a problem once we start cleaning up stale chunks.

            Assignee:
            Rustam Gusein-zade
            Reporter:
            Silvia Surroca
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated: