Skip to content

Commit

Permalink
[Feature](Nereids) Add explain tree functionality. (apache#25446)
Browse files Browse the repository at this point in the history
Add explain tree functionality which contains fragment ids for profile analysis.
```
mysql> explain tree select sum(l_orderkey) from lineitem, orders where l_orderkey = o_orderkey;
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Explain String(Nereids Planner)                                                                                                                                                                                   |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| [414]:[414: ResultSink]||[Fragment: 0]||VRESULT SINK||   MYSQL_PROTOCAL||                                                                                                                                         |
| --[414]:[414: VAGGREGATE (merge finalize)]||[Fragment: 0]||cardinality=1||                                                                                                                                        |
| ----[411]:[411: VEXCHANGE]||[Fragment: 0]||offset: 0||                                                                                                                                                            |
| ------[411]:[411: DataStreamSink]||[Fragment: 1]||STREAM DATA SINK||  EXCHANGE ID: 411||  UNPARTITIONED                                                                                                           |
| --------[408]:[408: VAGGREGATE (update serialize)]||[Fragment: 1]||cardinality=1||                                                                                                                                |
| ----------[402]:[402: VHASH JOIN]||[Fragment: 1]||join op: INNER JOIN(PARTITIONED)[]||cardinality=593,132,346||                                                                                                   |
| ------------[392]:[392: VEXCHANGE]||[Fragment: 1]||offset: 0||                                                                                                                                                    |
| --------------[392]:[392: DataStreamSink]||[Fragment: 2]||STREAM DATA SINK||  EXCHANGE ID: 392||  HASH_PARTITIONED                                                                                                |
| ----------------[386]:[386: VHIVE_SCAN_NODE]||[Fragment: 2]||table: lineitem||inputSplitNum=144, totalFileSize=16632158739, scanRanges=144||partition=1/1||cardinality=600037902, numNodes=1||pushdown agg=NONE|| |
| ------------[399]:[399: VEXCHANGE]||[Fragment: 1]||offset: 0||                                                                                                                                                    |
| --------------[399]:[399: DataStreamSink]||[Fragment: 3]||STREAM DATA SINK||  EXCHANGE ID: 399||  HASH_PARTITIONED                                                                                                |
| ----------------[393]:[393: VHIVE_SCAN_NODE]||[Fragment: 3]||table: orders||inputSplitNum=48, totalFileSize=3984213353, scanRanges=48||partition=1/1||cardinality=150000000, numNodes=1||pushdown agg=NONE||      |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
12 rows in set (0.04 sec)
```
  • Loading branch information
kaka11chen authored Nov 2, 2023
1 parent fb62280 commit 3ce1bda
Show file tree
Hide file tree
Showing 13 changed files with 102 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,7 @@ TINYINT: 'TINYINT';
TO: 'TO';
TRANSACTION: 'TRANSACTION';
TRASH: 'TRASH';
TREE: 'TREE';
TRIGGERS: 'TRIGGERS';
TRIM: 'TRIM';
TRUE: 'TRUE';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ userIdentify

explain
: (EXPLAIN planType? | DESC | DESCRIBE)
level=(VERBOSE | GRAPH | PLAN)?
level=(VERBOSE | TREE | GRAPH | PLAN)?
;

planType
Expand Down Expand Up @@ -1064,6 +1064,7 @@ nonReserved
| TIMESTAMPADD
| TIMESTAMPDIFF
| TRANSACTION
| TREE
| TRIGGERS
| TRUNCATE
| TYPE
Expand Down
13 changes: 10 additions & 3 deletions fe/fe-core/src/main/cup/sql_parser.cup
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,7 @@ terminal String
KW_TO,
KW_TRANSACTION,
KW_TRASH,
KW_TREE,
KW_TRIGGERS,
KW_TRIM,
KW_TRUE,
Expand Down Expand Up @@ -4316,15 +4317,19 @@ opt_builtin ::=

opt_explain_options ::=
{:
RESULT = new ExplainOptions(false, false);
RESULT = new ExplainOptions(false, false, false);
:}
| KW_VERBOSE
{:
RESULT = new ExplainOptions(true, false);
RESULT = new ExplainOptions(true, false, false);
:}
| KW_TREE
{:
RESULT = new ExplainOptions(false, true, false);
:}
| KW_GRAPH
{:
RESULT = new ExplainOptions(false, true);
RESULT = new ExplainOptions(false, false, true);
:}
;

Expand Down Expand Up @@ -7651,6 +7656,8 @@ keyword ::=
{: RESULT = id; :}
| KW_TRANSACTION:id
{: RESULT = id; :}
| KW_TREE:id
{: RESULT = id; :}
| KW_TEXT:id
{: RESULT = id; :}
| KW_TRIGGERS:id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
public class ExplainOptions {

private boolean isVerbose;

private boolean isTree;
private boolean isGraph;

private ExplainCommand.ExplainLevel explainLevel;
Expand All @@ -31,15 +33,20 @@ public ExplainOptions(ExplainCommand.ExplainLevel explainLevel) {
this.explainLevel = explainLevel;
}

public ExplainOptions(boolean isVerbose, boolean isGraph) {
public ExplainOptions(boolean isVerbose, boolean isTree, boolean isGraph) {
this.isVerbose = isVerbose;
this.isTree = isTree;
this.isGraph = isGraph;
}

public boolean isVerbose() {
return explainLevel == ExplainLevel.VERBOSE || isVerbose;
}

public boolean isTree() {
return explainLevel == ExplainLevel.TREE || isTree;
}

public boolean isGraph() {
return explainLevel == ExplainLevel.GRAPH || isGraph;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@

public class PlanTreePrinter {

private static final String DELIMITER = "||";

public static String printPlanExplanation(PlanTreeNode root) {
SimpleTreeNode rootNode = buildNode(root);
StringBuilder sb = new StringBuilder();
Expand All @@ -37,4 +39,21 @@ private static SimpleTreeNode buildNode(PlanTreeNode planNode) {
}
return node;
}

public static String printPlanTree(PlanTreeNode root) {
return buildTree(root, "");
}

private static String buildTree(PlanTreeNode planNode, String prefix) {
StringBuilder builder = new StringBuilder();
builder.append(prefix).append(planNode.getIds()).append(":")
.append(planNode.getExplainStr().replaceAll("\n", DELIMITER)).append("\n");
String childPrefix = prefix + "--";
planNode.getChildren().forEach(
child -> {
builder.append(buildTree(child, childPrefix));
}
);
return builder.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public enum ExplainLevel {
NONE(false),
NORMAL(false),
VERBOSE(false),
TREE(false),
GRAPH(false),
PARSED_PLAN(true),
ANALYZED_PLAN(true),
Expand Down
11 changes: 11 additions & 0 deletions fe/fe-core/src/main/java/org/apache/doris/planner/Planner.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,17 @@ public String getExplainString(ExplainOptions explainOptions) {
}
return PlanTreePrinter.printPlanExplanation(builder.getTreeRoot());
}
if (explainOptions.isTree()) {
// print the plan tree
PlanTreeBuilder builder = new PlanTreeBuilder(fragments);
try {
builder.build();
} catch (UserException e) {
LOG.warn("Failed to build explain plan tree", e);
return e.getMessage();
}
return PlanTreePrinter.printPlanTree(builder.getTreeRoot());
}

// print text plan
org.apache.doris.thrift.TExplainLevel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,16 @@ public void testExplainVerbose() {
Assertions.assertEquals(ExplainLevel.VERBOSE, explainLevel);
}

@Test
public void testExplainTree() {
String sql = "explain tree select `AD``D` from t1 where a = 1";
NereidsParser nereidsParser = new NereidsParser();
LogicalPlan logicalPlan = nereidsParser.parseSingle(sql);
ExplainCommand explainCommand = (ExplainCommand) logicalPlan;
ExplainLevel explainLevel = explainCommand.getLevel();
Assertions.assertEquals(ExplainLevel.TREE, explainLevel);
}

@Test
public void testExplainGraph() {
String sql = "explain graph select `AD``D` from t1 where a = 1";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,14 +136,14 @@ public void testExplicitlyBroadcastJoin() throws Exception {
StmtExecutor stmtExecutor = new StmtExecutor(ctx, sql);
stmtExecutor.execute();
Planner planner = stmtExecutor.planner();
String plan = planner.getExplainString(new ExplainOptions(false, false));
String plan = planner.getExplainString(new ExplainOptions(false, false, false));
Assert.assertEquals(1, StringUtils.countMatches(plan, "INNER JOIN(BROADCAST)"));

sql = "explain select * from db1.tbl1 join [SHUFFLE] db1.tbl2 on tbl1.k1 = tbl2.k3";
stmtExecutor = new StmtExecutor(ctx, sql);
stmtExecutor.execute();
planner = stmtExecutor.planner();
plan = planner.getExplainString(new ExplainOptions(false, false));
plan = planner.getExplainString(new ExplainOptions(false, false, false));
Assert.assertEquals(1, StringUtils.countMatches(plan, "INNER JOIN(PARTITIONED)"));
}

Expand All @@ -153,7 +153,7 @@ public void testBroadcastJoinCostThreshold() throws Exception {
StmtExecutor stmtExecutor = new StmtExecutor(ctx, sql);
stmtExecutor.execute();
Planner planner = stmtExecutor.planner();
String plan = planner.getExplainString(new ExplainOptions(false, false));
String plan = planner.getExplainString(new ExplainOptions(false, false, false));
Assert.assertEquals(1, StringUtils.countMatches(plan, "INNER JOIN(BROADCAST)"));

double originThreshold = ctx.getSessionVariable().autoBroadcastJoinThreshold;
Expand All @@ -162,7 +162,7 @@ public void testBroadcastJoinCostThreshold() throws Exception {
stmtExecutor = new StmtExecutor(ctx, sql);
stmtExecutor.execute();
planner = stmtExecutor.planner();
plan = planner.getExplainString(new ExplainOptions(false, false));
plan = planner.getExplainString(new ExplainOptions(false, false, false));
Assert.assertEquals(1, StringUtils.countMatches(plan, "INNER JOIN(PARTITIONED)"));
} finally {
ctx.getSessionVariable().autoBroadcastJoinThreshold = originThreshold;
Expand Down
Loading

0 comments on commit 3ce1bda

Please sign in to comment.