1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
// When running explain commands with "executionStats" verbosity, checks that the explain output
// includes "executionTimeMicros"/"executionTimeNanos" only if requested.
// "executionTimeMillisEstimate" will always be present in the explain output.
(function() {
"use strict";
load("jstests/libs/analyze_plan.js"); // For getAllPlanStages().
let conn = MongoRunner.runMongod({});
assert.neq(conn, null, "mongod failed to start up");
let db = conn.getDB("test");
let coll = db.explain_execution_time_in_nanoseconds;
coll.drop();
assert.commandWorked(coll.createIndex({x: 1}));
assert.commandWorked(coll.createIndex({y: 1}));
for (let i = 0; i < 1000; i++) {
assert.commandWorked(coll.insert({x: i, y: i * 2}));
}
function verifyStages(execStages, microAndNanosExpected) {
const allStages = getAllPlanStages(execStages);
assert.eq(execStages.hasOwnProperty("executionTimeMicros"), microAndNanosExpected);
assert.eq(execStages.hasOwnProperty("executionTimeNanos"), microAndNanosExpected);
for (let stage of allStages) {
assert(stage.hasOwnProperty("executionTimeMillisEstimate"), stage);
assert.eq(stage.hasOwnProperty("executionTimeMicros"), microAndNanosExpected, stage);
assert.eq(stage.hasOwnProperty("executionTimeNanos"), microAndNanosExpected, stage);
}
}
// Test explain on find command.
let explainResult = coll.find({x: {$gt: 500}}).explain("executionStats");
let executionStages = explainResult.executionStats.executionStages;
assert(executionStages.hasOwnProperty("executionTimeMillisEstimate"), executionStages);
verifyStages(executionStages, false);
// Test explain on aggregate command.
const pipeline = [{$match: {x: {$gt: 500}}}, {$addFields: {xx: {$add: ["$x", "$y"]}}}];
// Run an explain command when the "executionTimeMicros"/"executionTimeNanos" should be omitted.
explainResult = coll.explain("executionStats").aggregate(pipeline);
executionStages = explainResult.stages;
assert.neq(executionStages.length, 0, executionStages);
for (let executionStage of executionStages) {
// We should only have "executionTimeMillisEstimate" in the explain output.
assert(executionStage.hasOwnProperty("executionTimeMillisEstimate"), executionStage);
assert(!executionStage.hasOwnProperty("executionTimeMicros"), executionStage);
assert(!executionStage.hasOwnProperty("executionTimeNanos"), executionStage);
if (executionStage.hasOwnProperty("$cursor")) {
const stages = executionStage["$cursor"]["executionStats"]["executionStages"];
verifyStages(stages, false);
}
}
MongoRunner.stopMongod(conn);
// Request microsecond precision for the estimates of execution time.
conn = MongoRunner.runMongod({setParameter: "internalMeasureQueryExecutionTimeInNanoseconds=true"});
assert.neq(conn, null, "mongod failed to start up");
db = conn.getDB("test");
coll = db.explain_execution_time_in_microseconds;
explainResult = coll.find({x: {$gt: 500}}).explain("executionStats");
let isSBE = explainResult.explainVersion === "2";
executionStages = explainResult.executionStats.executionStages;
assert(executionStages.hasOwnProperty("executionTimeMillisEstimate"), executionStages);
verifyStages(executionStages, isSBE);
explainResult = coll.explain("executionStats").aggregate(pipeline);
executionStages = explainResult.stages;
isSBE = explainResult.explainVersion === "2";
assert.neq(executionStages.length, 0, executionStages);
for (let executionStage of executionStages) {
assert(executionStage.hasOwnProperty("executionTimeMillisEstimate"), executionStage);
// "executionTimeMicros"/"executionTimeNanos" is only added to SBE stages, not to agg stages.
assert(!executionStage.hasOwnProperty("executionTimeMicros"), executionStage);
assert(!executionStage.hasOwnProperty("executionTimeNanos"), executionStage);
if (executionStage.hasOwnProperty("$cursor")) {
const stages = executionStage["$cursor"]["executionStats"]["executionStages"];
verifyStages(stages, isSBE);
}
}
MongoRunner.stopMongod(conn);
})();
|