[Feature](Nereids) Add explain tree functionality. (#25446)

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)
```
This commit is contained in:
Qi Chen
2023-11-02 14:06:24 +08:00
committed by GitHub
parent fb622800aa
commit 3ce1bdae84
13 changed files with 102 additions and 45 deletions

View File

@ -23,6 +23,8 @@ import org.apache.doris.nereids.trees.plans.commands.ExplainCommand.ExplainLevel
public class ExplainOptions {
private boolean isVerbose;
private boolean isTree;
private boolean isGraph;
private ExplainCommand.ExplainLevel explainLevel;
@ -31,8 +33,9 @@ public class ExplainOptions {
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;
}
@ -40,6 +43,10 @@ public class ExplainOptions {
return explainLevel == ExplainLevel.VERBOSE || isVerbose;
}
public boolean isTree() {
return explainLevel == ExplainLevel.TREE || isTree;
}
public boolean isGraph() {
return explainLevel == ExplainLevel.GRAPH || isGraph;
}

View File

@ -23,6 +23,8 @@ import hu.webarticum.treeprinter.TraditionalTreePrinter;
public class PlanTreePrinter {
private static final String DELIMITER = "||";
public static String printPlanExplanation(PlanTreeNode root) {
SimpleTreeNode rootNode = buildNode(root);
StringBuilder sb = new StringBuilder();
@ -37,4 +39,21 @@ public class PlanTreePrinter {
}
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();
}
}

View File

@ -40,6 +40,7 @@ public class ExplainCommand extends Command implements NoForward {
NONE(false),
NORMAL(false),
VERBOSE(false),
TREE(false),
GRAPH(false),
PARSED_PLAN(true),
ANALYZED_PLAN(true),

View File

@ -70,6 +70,17 @@ public abstract class Planner {
}
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