diff options
Diffstat (limited to 'jstests/core/query/distinct/distinct_index1.js')
-rw-r--r-- | jstests/core/query/distinct/distinct_index1.js | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/jstests/core/query/distinct/distinct_index1.js b/jstests/core/query/distinct/distinct_index1.js new file mode 100644 index 00000000000..75a7f8adc22 --- /dev/null +++ b/jstests/core/query/distinct/distinct_index1.js @@ -0,0 +1,84 @@ +/** + * Analyzes execution stats for indexed distinct. + * @tags: [ + * assumes_balancer_off, + * assumes_read_concern_local, + * ] + */ +(function() { +load("jstests/libs/analyze_plan.js"); // For getPlanStage. + +const coll = db.distinct_index1; +coll.drop(); + +function getHash(num) { + return Math.floor(Math.sqrt(num * 123123)) % 10; +} + +function getDistinctExplainWithExecutionStats(field, query) { + const explain = coll.explain("executionStats").distinct(field, query || {}); + assert(explain.hasOwnProperty("executionStats"), explain); + return explain; +} + +const bulk = coll.initializeUnorderedBulkOp(); +for (let i = 0; i < 1000; i++) { + bulk.insert({a: getHash(i * 5), b: getHash(i)}); +} +assert.commandWorked(bulk.execute()); + +let explain = getDistinctExplainWithExecutionStats("a"); +// Collection scan looks at all 1000 documents and gets 1000 distinct values. Looks at 0 index +// keys. +assert.eq(1000, explain.executionStats.nReturned); +assert.eq(0, explain.executionStats.totalKeysExamined); +assert.eq(1000, explain.executionStats.totalDocsExamined); + +explain = getDistinctExplainWithExecutionStats("a", {a: {$gt: 5}}); +// Collection scan looks at all 1000 documents and gets 398 distinct values which match the +// query. Looks at 0 index keys. +assert.eq(398, explain.executionStats.nReturned); +assert.eq(0, explain.executionStats.totalKeysExamined); +assert.eq(1000, explain.executionStats.totalDocsExamined); + +explain = getDistinctExplainWithExecutionStats("b", {a: {$gt: 5}}); +// Collection scan looks at all 1000 documents and gets 398 distinct values which match the +// query. Looks at 0 index keys. +assert.eq(398, explain.executionStats.nReturned); +assert.eq(0, explain.executionStats.totalKeysExamined); +assert.eq(1000, explain.executionStats.totalDocsExamined); + +assert.commandWorked(coll.createIndex({a: 1})); + +explain = getDistinctExplainWithExecutionStats("a"); +// There are only 10 values. We use the fast distinct hack and only examine each value once. +assert.eq(10, explain.executionStats.nReturned); +assert.lte(10, explain.executionStats.totalKeysExamined); + +explain = getDistinctExplainWithExecutionStats("a", {a: {$gt: 5}}); +// Only 4 values of a are >= 5 and we use the fast distinct hack. +assert.eq(4, explain.executionStats.nReturned); +assert.eq(4, explain.executionStats.totalKeysExamined); +assert.eq(0, explain.executionStats.totalDocsExamined); + +explain = getDistinctExplainWithExecutionStats("b", {a: {$gt: 5}}); +// We can't use the fast distinct hack here because we're distinct-ing over 'b'. +assert.eq(398, explain.executionStats.nReturned); +assert.eq(398, explain.executionStats.totalKeysExamined); +assert.eq(398, explain.executionStats.totalDocsExamined); + +// Test that a distinct over a trailing field of the index can be covered. +assert.commandWorked(coll.dropIndexes()); +assert.commandWorked(coll.createIndex({a: 1, b: 1})); +explain = getDistinctExplainWithExecutionStats("b", {a: {$gt: 5}, b: {$gt: 5}}); +assert.lte(explain.executionStats.nReturned, 171); +assert.eq(0, explain.executionStats.totalDocsExamined); + +// Should use an index scan over the hashed index. +assert.commandWorked(coll.dropIndexes()); +assert.commandWorked(coll.createIndex({a: "hashed"})); +explain = getDistinctExplainWithExecutionStats("a", {$or: [{a: 3}, {a: 5}]}); +assert.eq(188, explain.executionStats.nReturned); +const indexScanStage = getPlanStage(getWinningPlan(explain.queryPlanner), "IXSCAN"); +assert.eq("hashed", indexScanStage.keyPattern.a); +})(); |