ExportXMLWordPrintableJSON

    • Type: Bug
    • Resolution: Unresolved
    • Priority: Major - P3
    • None
    • Affects Version/s: None
    • Component/s: None
    • Query Optimization
    • ALL
    • Hide

       

      
      /**
       * JOO wrong results: an indexed nested loop join that probes a *multikey* compound index returns
       * the same foreign document once per array element.
       *
       * createIndexProbeQSN() builds the IndexEntry with isMultikey=false regardless of the catalog, so
       * buildIndexedJoinIndexProbe() never adds the UniqueRoaring dedup stage. The probe seeks
       * [x, MinKey] .. [x, MaxKey] on {y: 1, tags: 1}, which matches one key per element of "tags".
       * The join predicate field itself (y) is scalar, so PathArrayness does not block the plan.
       *
       * The join method is forced here for determinism; the same plan is chosen naturally e.g. with
       * 3 local documents and 20000 foreign documents.
       */
      const conn = MongoRunner.runMongod({
          setParameter: {
              internalEnableJoinOptimization: true,
              featureFlagPathArrayness: true,
              featureFlagCostBasedRanker: true,
              internalEnableJoinPlanCache: false,
              internalJoinMethod: "INLJ",
          },
      });
      const db = conn.getDB("test");
      try {
          assert.commandWorked(db.a.insert({_id: 1, x: 1}));
          assert.commandWorked(db.b.insert({_id: 1, y: 1, tags: [1, 2, 3]}));
          assert.commandWorked(db.a.createIndex({x: 1}));
          assert.commandWorked(db.b.createIndex({y: 1, tags: 1}));
      
          const pipeline = [{$lookup: {from: "b", localField: "x", foreignField: "y", as: "b"}}, {$unwind: "$b"}];
          function run(joinOpt) {
              assert.commandWorked(db.adminCommand({setParameter: 1, internalEnableJoinOptimization: joinOpt}));
              return db.a.aggregate(pipeline).toArray();
          }
          const expected = run(false);
          assert.eq(expected.length, 1, tojson(expected));
          const actual = run(true);
          // assert: expected 3 to equal 1 : join optimization returned duplicates: [ { "_id" : 1, "x" : 1, "b" : { "_id" : 1, "y" : 1, "tags" : [ 1, 2, 3 ] } }, ... ]
          assert.eq(actual.length, 1, "join optimization returned duplicates: " + tojson(actual));
      } finally {
          MongoRunner.stopMongod(conn);
      }
      
      
      

       

      Show
        /** * JOO wrong results: an indexed nested loop join that probes a *multikey* compound index returns * the same foreign document once per array element. * * createIndexProbeQSN() builds the IndexEntry with isMultikey= false regardless of the catalog, so * buildIndexedJoinIndexProbe() never adds the UniqueRoaring dedup stage. The probe seeks * [x, MinKey] .. [x, MaxKey] on {y: 1, tags: 1}, which matches one key per element of "tags" . * The join predicate field itself (y) is scalar, so PathArrayness does not block the plan. * * The join method is forced here for determinism; the same plan is chosen naturally e.g. with * 3 local documents and 20000 foreign documents. */ const conn = MongoRunner.runMongod({ setParameter: { internalEnableJoinOptimization: true , featureFlagPathArrayness: true , featureFlagCostBasedRanker: true , internalEnableJoinPlanCache: false , internalJoinMethod: "INLJ" , }, }); const db = conn.getDB( "test" ); try { assert.commandWorked(db.a.insert({_id: 1, x: 1})); assert.commandWorked(db.b.insert({_id: 1, y: 1, tags: [1, 2, 3]})); assert.commandWorked(db.a.createIndex({x: 1})); assert.commandWorked(db.b.createIndex({y: 1, tags: 1})); const pipeline = [{$lookup: {from: "b" , localField: "x" , foreignField: "y" , as: "b" }}, {$unwind: "$b" }]; function run(joinOpt) { assert.commandWorked(db.adminCommand({setParameter: 1, internalEnableJoinOptimization: joinOpt})); return db.a.aggregate(pipeline).toArray(); } const expected = run( false ); assert.eq(expected.length, 1, tojson(expected)); const actual = run( true ); // assert: expected 3 to equal 1 : join optimization returned duplicates: [ { "_id" : 1, "x" : 1, "b" : { "_id" : 1, "y" : 1, "tags" : [ 1, 2, 3 ] } }, ... ] assert.eq(actual.length, 1, "join optimization returned duplicates: " + tojson(actual)); } finally { MongoRunner.stopMongod(conn); }  
    • None
    • None
    • None
    • None
    • None
    • None
    • None

      createIndexProbeQSN() in reorder_joins.cpp builds the IndexEntry with isMultikey=false regardless of the catalog, so buildIndexedJoinIndexProbe() never adds the dedup stage. Probing {y: 1, tags: 1} with bounds [x, MinKey]..[x, MaxKey] returns the foreign document once per element of tags. The join field itself is scalar, so path arrayness does not block the plan; INLJ is chosen naturally with a large foreign collection.

            Assignee:
            Unassigned
            Reporter:
            Max Verbinnen
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated: