The EXPLAIN
clause lets users inspect the plans of their queries.
EXPLAIN
queries start out by parsing the inner query (what’s inside the EXPLAIN
clause) and getting the query plan, which is a tree of logical operators. These steps use existing methods described in Lexical and Syntactic Analysis, Semantic Analysis and Symbol Generation and Planning.
With the plan made, the interpreter moves on to generating the output. The plan::PrettyPrint
function creates a hierarchical visitor (PlanPrinter
) that goes through the plan. PlanPrinter
contains a visit function for each operator. Visit functions make the output for the current operator and call the accept function of its child operator(s) so that plan traversal can continue.
The PROFILE
clause creates a detailed report about the execution of the query plan, with time and hits statistics for each operator.
Compared to EXPLAIN
, there are similarities and differences in the output:
PROFILE
clauses execute the inner query in order to get time + hits data.PROFILE
clauses lack information about operator “arguments”, e.g. * Produce
vs * Produce **{m, n}**
The first steps are as in [EXPLAIN
queries start out by parsing the inner query (what’s inside the EXPLAIN
clause) and getting the query plan, which is a tree of logical operators. These steps use existing methods described in Lexical and Syntactic Analysis, Semantic Analysis and Symbol Generation and Planning.](https://memgraph.notion.site/EXPLAIN-queries-start-out-by-parsing-the-inner-query-what-s-inside-the-EXPLAIN-clause-and-getting--f7da3f9f63824619a4167326f11a20d7) and result in the inner query plan.
With the plan made, the interpreter creates a PullPlan
(and thus a cursor) and starts pulling from the cursor. Each operator’s cursor has a SCOPED_PROFILE_OP
call that executes on pull.
These calls are the key part:
SCOPED_PROFILE_OP
, counting the number of calls for each operator corresponds to getting the number of operator hits.ScopedProfile
ProfilingStats
nodes that corresponds to the plan tree
In short, the above means that an operator tree with profiling statistics for each operator is constructed during query execution.
Next, the interpreter switches to ProfilingStatsWithTotalTime
(to get absolute time data) and traverses the operator tree to create the output table (ProfilingStatsToTableHelper::Output
). This is recursive DFS that visits children branches and generates their table row before the parent’s table row.