feat: tool to graphically display plans (#803)

* feat: tool to graphically display plans

* docs: Add note to CONTRIBUTING.md

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
pull/24376/head
Andrew Lamb 2021-02-15 08:03:12 -05:00 committed by GitHub
parent 0fe590cedd
commit da39e4099c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 91 additions and 0 deletions

View File

@ -118,6 +118,44 @@ can use all the features of that crate. For example, to disable the
RUST_LOG=debug,hyper::proto::h1=info,h2=info cargo test --workspace
```
### Visually showing explain plans
Some query plans are output in the log in [graphviz](https://graphviz.org/) format. To display them you can use the `tools/iplan` helper.
For example, if you want to display this plan:
```
// Begin DataFusion GraphViz Plan (see https://graphviz.org)
digraph {
subgraph cluster_1
{
graph[label="LogicalPlan"]
2[shape=box label="SchemaPivot"]
3[shape=box label="Projection: "]
2 -> 3 [arrowhead=none, arrowtail=normal, dir=back]
4[shape=box label="Filter: Int64(0) LtEq #time And #time Lt Int64(10000) And #host Eq Utf8(_server01_)"]
3 -> 4 [arrowhead=none, arrowtail=normal, dir=back]
5[shape=box label="TableScan: attributes projection=None"]
4 -> 5 [arrowhead=none, arrowtail=normal, dir=back]
}
subgraph cluster_6
{
graph[label="Detailed LogicalPlan"]
7[shape=box label="SchemaPivot\nSchema: [non_null_column:Utf8]"]
8[shape=box label="Projection: \nSchema: []"]
7 -> 8 [arrowhead=none, arrowtail=normal, dir=back]
9[shape=box label="Filter: Int64(0) LtEq #time And #time Lt Int64(10000) And #host Eq Utf8(_server01_)\nSchema: [color:Utf8;N, time:Int64]"]
8 -> 9 [arrowhead=none, arrowtail=normal, dir=back]
10[shape=box label="TableScan: attributes projection=None\nSchema: [color:Utf8;N, time:Int64]"]
9 -> 10 [arrowhead=none, arrowtail=normal, dir=back]
}
}
// End DataFusion GraphViz Plan
```
You can pipe it to `iplan` and render as a .pdf
## Running `rustfmt` and `clippy`
CI will check the code formatting with [`rustfmt`] and Rust best practices with [`clippy`].

53
tools/iplan Executable file
View File

@ -0,0 +1,53 @@
#!/usr/bin/env python
#
# This script extracts all plans from its stdin, invokes dot on them
# to make a multi-page pdf / open to display them
#
import os
import fileinput
files = []
in_graphviz = False
# Note we combine multiple digraphs
for line in fileinput.input():
line = line.strip()
if line.startswith("// Begin DataFusion GraphViz Plan"):
filename = "/tmp/plan{}.ps".format(len(files))
files.append(filename)
f = open(filename, "w")
in_graphviz = True
if in_graphviz:
f.write(line)
f.write("\n")
if line.startswith("// End DataFusion GraphViz Plan"):
in_graphviz = False
f = None
# try to ensure any open is closed
f = None
# TODO make this not mac specific
if len(files) > 0:
#print("Found files: {}".format(files))
print("Found {} graphs, converting to ps".format(len(files)))
# convert them to ps files
ps_files = []
for file in files:
output_file = "{}.pdf".format(file)
os.system("dot -Tpdf < {} > {}.pdf".format(file, output_file))
ps_files.append(output_file)
# combine all the postscript files together
cmd = "gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=/tmp/plan.pdf {}".format(" ".join(ps_files))
print("Running command:", cmd)
os.system(cmd)
print("Opening with system viewer")
os.system('open /tmp/plan.pdf')