Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Print the plan's tree structure in PlanPrinter #12101

Closed
wants to merge 1 commit into from

Conversation

wagnermarkd
Copy link
Contributor

The current PlanPrinter (used for EXPLAIN queries) prints out indented plans with each node prefixed by a dash. That makes it a bit difficult to follow the hierarchy when the sources for a node (e.g. a join) don't fit on the same screen.

We can use box drawing characters from Unicode to illustrate the tree structure and allow a reader to follow the line from one part of the plan to another. This is the same method that the tree command uses on most systems.

A redacted example of an actual query:

Output[rows] => [rows:bigint]
└── TableCommit[XXXX:XXXX.XXXX] => [rows:bigint]
    └── LocalExchange[SINGLE] () => partialrows:bigint, fragment:varbinary
        └── RemoteExchange[GATHER] => partialrows:bigint, fragment:varbinary
            └── TableWriter => [partialrows:bigint, fragment:varbinary]
                │   XXXX := expr_161
                │   XXXX := expr_162
                │   XXXX := count
                │   XXXX := count_166
                └── LocalExchange[SINGLE] () => expr_161:boolean, expr_162:boolean, count_166:bigint, count:bigint
                    └── RemoteExchange[REPARTITION] => expr_161:boolean, expr_162:boolean, count_166:bigint, count:bigint
                        └── Project[] => [expr_161:boolean, expr_162:boolean, count_166:bigint, count:bigint]
                            └── Aggregate(FINAL)[expr_161, expr_162][$hashvalue] => [expr_161:boolean, expr_162:boolean, $hashvalue:bigint, count_166:bigint, count:bigint]
                                │   count_166 := "count"("count_203")
                                │   count := "count"("count_204")
                                └── LocalExchange[HASH][$hashvalue] ("expr_161", "expr_162") => expr_161:boolean, expr_162:boolean, count_204:bigint, count_203:bigint, $hashvalue:bigint
                                    └── RemoteExchange[REPARTITION][$hashvalue_205] => expr_161:boolean, expr_162:boolean, count_204:bigint, count_203:bigint, $hashvalue_205:bigint
                                        └── Aggregate(PARTIAL)[expr_161, expr_162][$hashvalue_206] => [expr_161:boolean, expr_162:boolean, $hashvalue_206:bigint, count_204:bigint, count_203:bigint]
                                            │   count_204 := "count"("expr_163")
                                            │   count_203 := "count"("expr_164") (mask = expr$distinct)
                                            └── MarkDistinct[distinct=expr_161:boolean, expr_162:boolean, expr_164:varchar marker=expr$distinct][$hashvalue_207] => [expr_161:boolean, expr_162:boolean, expr_163:integer, expr_164:varchar, $hashvalue_206:bigint, $hashvalue_207:bigint, expr$distinct:boolean]
                                                └── LocalExchange[HASH][$hashvalue_207] ("expr_161", "expr_162", "expr_164") => expr_161:boolean, expr_162:boolean, expr_163:integer, expr_164:varchar, $hashvalue_206:bigint, $hashvalue_207:bigint
                                                    └── RemoteExchange[REPARTITION][$hashvalue_209] => expr_161:boolean, expr_162:boolean, expr_163:integer, expr_164:varchar, $hashvalue_208:bigint, $hashvalue_209:bigint
                                                        └── Project[] => [expr_161:boolean, expr_162:boolean, expr_163:integer, expr_164:varchar, $hashvalue_218:bigint, $hashvalue_219:bigint]
                                                            │   $hashvalue_218 := "combine_hash"("combine_hash"(bigint '0', COALESCE("$operator$hash_code"("expr_161"), 0)), COALESCE("$operator$hash_code"("expr_162"), 0))
                                                            │   $hashvalue_219 := "combine_hash"("combine_hash"("combine_hash"(bigint '0', COALESCE("$operator$hash_code"("expr_161"), 0)), COALESCE("$operator$hash_code"("expr_162"), 0)), COALESCE("$operator$hash_code"("expr_164"), 0))
                                                            └── Project[] => [expr_161:boolean, expr_162:boolean, expr_163:integer, expr_164:varchar]
                                                                │   expr_161 := (NOT ("concat" IS NULL))
                                                                │   expr_162 := (NOT ("XXXX_110" IS NULL))
                                                                │   expr_163 := 1
                                                                │   expr_164 := COALESCE("concat", "XXXX_110")
                                                                └── FullJoin[("concat" = "XXXX_110") AND ("XXXX" = "expr_131") AND ("strpos"("regexp_extract", "field") = BIGINT '1')][$hashvalue_210, $hashvalue_215] => [concat:varchar, XXXX_110:varchar]
                                                                    │   Distribution: PARTITIONED
                                                                    ├── RemoteExchange[REPARTITION][$hashvalue_210] => regexp_extract:varchar, XXXX:varchar, concat:varchar, $hashvalue_210:bigint
                                                                    │   └── Project[] => [regexp_extract:varchar, XXXX:varchar, concat:varchar, $hashvalue_214:bigint]
                                                                    │       │   $hashvalue_214 := "combine_hash"("combine_hash"(bigint '0', COALESCE("$operator$hash_code"("concat"), 0)), COALESCE("$operator$hash_code"("XXXX"), 0))
                                                                    │       └── Aggregate(FINAL)[regexp_extract, XXXX, concat][$hashvalue_211] => [regexp_extract:varchar, XXXX:varchar, concat:varchar, $hashvalue_211:bigint]
                                                                    │           └── LocalExchange[HASH][$hashvalue_211] ("regexp_extract", "XXXX", "concat") => regexp_extract:varchar, XXXX:varchar, concat:varchar, $hashvalue_211:bigint
                                                                    │               └── RemoteExchange[REPARTITION][$hashvalue_212] => regexp_extract:varchar, XXXX:varchar, concat:varchar, $hashvalue_212:bigint
                                                                    │                   └── Aggregate(PARTIAL)[regexp_extract, XXXX, concat][$hashvalue_213] => [regexp_extract:varchar, XXXX:varchar, concat:varchar, $hashvalue_213:bigint]
                                                                    │                       └── Project[] => [XXXX:varchar, concat:varchar, regexp_extract:varchar, $hashvalue_213:bigint]
                                                                    │                           │   $hashvalue_213 := "combine_hash"("combine_hash"("combine_hash"(bigint '0', COALESCE("$operator$hash_code"("regexp_extract"), 0)), COALESCE("$operator$hash_code"("XXXX"), 0)), COALESCE("$operator$hash_code"("concat"), 0))
                                                                    │                           └── Project[] => [XXXX:varchar, concat:varchar, regexp_extract:varchar]
                                                                    │                               │   regexp_extract := "regexp_extract"("XXXX", CAST('XXXX' AS joniregexp), BIGINT '1')
                                                                    │                               └── FilterProject[filterPredicate = ((("XXXX" IS NULL) OR (NOT ("XXXX" LIKE 'XXXX'))) AND (("XXXX" IS NULL) OR (NOT ("XXXX" LIKE 'XXXX'))))] => [XXXX:varchar, XXXX:varchar, concat:varchar]
                                                                    │                                   └── ScanFilterProject[table = XXXX:XXXX:XXXX, filterPredicate = ((("XXXX" = CAST('XXXX' AS varchar)) AND ("XXXX" <> CAST('XXXX' AS varchar))) AND (NOT ("XXXX" LIKE 'XXXX')))] => [XXXX:varchar, XXXX:varchar, XXXX:varchar, concat:varchar]
                                                                    │                                           concat := "concat"("concat"(CAST('XXXX' AS varchar), "XXXX"), CAST('XXXX' AS varchar))
                                                                    │                                           LAYOUT: XXXX.XXXX
                                                                    │                                           XXXX := XXXX:string:4:REGULAR
                                                                    │                                           XXXX := XXXX:string:-1:PARTITION_KEY
                                                                    │                                             :: [[XXXX], [XXXX]]
                                                                    │                                           XXXX := XXXX:string:2:REGULAR
                                                                    │                                           XXXX := XXXX:string:3:REGULAR
                                                                    │                                           XXXX := XXXX:string:5:REGULAR
                                                                    │                                           XXXX := XXXX:string:1:REGULAR
                                                                    │                                           XXXX:string:-1:PARTITION_KEY
                                                                    │                                               :: [[XXXX, XXXX]]
                                                                    └── LocalExchange[HASH][$hashvalue_215] ("XXXX_110", "expr_131") => XXXX_110:varchar, field:varchar, expr_131:varchar, $hashvalue_215:bigint
                                                                        └── RemoteExchange[REPARTITION][$hashvalue_216] => XXXX_110:varchar, field:varchar, expr_131:varchar, $hashvalue_216:bigint
                                                                            └── Project[] => [XXXX_110:varchar, field:varchar, expr_131:varchar, $hashvalue_217:bigint]
                                                                                │   $hashvalue_217 := "combine_hash"("combine_hash"(bigint '0', COALESCE("$operator$hash_code"("XXXX_110"), 0)), COALESCE("$operator$hash_code"("expr_131"), 0))
                                                                                └── Project[] => [XXXX_110:varchar, field:varchar, expr_131:varchar]
                                                                                    │   expr_131 := CAST((CASE WHEN ("XXXX_111" = CAST('XXXX' AS varchar)) THEN 'XXXX' WHEN ("XXXX_111" = CAST('XXXX' AS varchar)) THEN CAST('XXXX' AS varchar(11)) END) AS varchar)
                                                                                    └── Unnest [replicate=XXXX_110:varchar, XXXX_111:varchar, unnest=XXXX:array(varchar)] => [XXXX_110:varchar, XXXX_111:varchar, field:varchar]
                                                                                        └── TableScan[XXXX:XXXX:XXXX] => [XXXX_110:varchar, XXXX:array(varchar), XXXX_111:varchar]
                                                                                                LAYOUT: XXXX.XXXX
                                                                                                XXXX_111 := XXXX:string:3:REGULAR
                                                                                                XXXX_110 := XXXX:string:0:REGULAR
                                                                                                XXXX := XXXX:array<string>:1:REGULAR
                                                                                                XXXX:string:-1:PARTITION_KEY
                                                                                                    :: [[XXXX], [XXXX]]

@wenleix
Copy link
Contributor

wenleix commented Jan 31, 2019

This looks like a nice feature to have -- I personally found sometimes it's difficult to trace the parent nodes in plan. What do you think, @raghavsethi , @nezihyigitbasi ?

@raghavsethi
Copy link
Contributor

raghavsethi commented Jan 31, 2019

I agree. Unfortunately, I wish I'd known about this before I refactored a whole bunch of code in PlanPrinter (#11960). I'm just about to merge that. I will have to ask that you rebase on top of that after that happens, because that's a lot more complicated. Sorry!

@nezihyigitbasi
Copy link
Contributor

Looks useful, thanks @wagnermarkd.

@raghavsethi
Copy link
Contributor

Merged my branch, please let me know if you intend to rebase on top of it.

@stale
Copy link

stale bot commented Aug 4, 2019

This pull request has been automatically marked as stale because it has not had recent activity. If you'd still like this PR merged, please comment on the task, make sure you've addressed reviewer comments, and rebase on the latest master. Thank you for your contributions!

@stale stale bot added the stale label Aug 4, 2019
@stale stale bot closed this Aug 11, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants