Visualization Utilities#

Module name: postbound.vis

Note that this module requires a number of additional dependencies. They can be installed via the vis extra:

pip install postbound[vis]

Contains utilities to visualize different PostBOUND objects.

postbound.vis.annotate_cards(table: TableReference, *, query: SqlQuery, database: Database | None = None) str#

Annotates the nodes of a join graph with true cardinalities before and after filters.

Cardinalities are calculated by issuing actual count(*) queries to the database. Two values are reported: the total cardinality of the table (before filters) and the cardinality after applying all applicable filter predicates from the query.

Parameters:
  • table (TableReference) – The table to estimate

  • query (SqlQuery) – The SQL query being optimized. This is required to infer all filter predicates

  • database (Optional[Database], optional) – The database to calculate the cardinalities on. If None, the current database from the DatabasePool is used.

Return type:

str

See also

plot_join_graph

postbound.vis.annotate_estimates(node: QueryPlan) str#

Annotates the nodes of a query plan with estimated cost and cardinality.

See also

plot_query_plan

Parameters:

node (QueryPlan)

Return type:

str

postbound.vis.annotate_filter_cards(table: TableReference, *, query: SqlQuery, database: Database | None = None) str#

Annotates the nodes of a join graph with true cardinalities after filters.

Cardinalities are calculated by issuing actual count(*) queries to the database. All applicable filter predicates are included in the query.

Parameters:
  • table (TableReference) – The table to estimate

  • query (SqlQuery) – The SQL query being optimized. This is required to infer all filter predicates

  • database (Optional[Database], optional) – The database to calculate the cardinalities on. If None, the current database from the DatabasePool is used.

Return type:

str

See also

plot_join_graph

postbound.vis.estimated_cards(table: TableReference, *, query: SqlQuery, database: Database | None = None) str#

Annotates the nodes of a join graph with estimated cardinalities.

Estimated cardinalities are obtained by asking the actual query optimizer from the database. Usually, they are calculated after all matching filter predicates have been applied.

Parameters:
  • table (TableReference) – The table to estimate

  • query (SqlQuery) – The SQL query being optimized. This is required to infer all filter predicates

  • database (Optional[Database], optional) – The database whose optimizer is used to estimate the cardinalities. If None, the current database from the DatabasePool is used.

Return type:

str

See also

plot_join_graph

postbound.vis.force_directed_layout(elements: Iterable[T], difference_score: Callable[[T, T], float]) dict[T, ndarray]#

Lays out the supplied elements in a 2D-space according to the difference score.

Pairs of points with a large difference score are positioned further apart than points with a low difference score.

The returned dictionary maps each of the input element to the pair of (x, y) coordinates.

Parameters:
  • elements (Iterable[T])

  • difference_score (Callable[[T, T], float])

Return type:

dict[T, ndarray]

postbound.vis.plot_analyze_plan(plan: QueryPlan, *, skip_intermediates: bool = False, **kwargs) Graph#

Creates a Graphviz visualization of an EXPLAIN ANALYZE query plan.

This is a convenience wrapper around plot_query_plan that uses a default annotation generator suitable for showing runtime information contained in EXPLAIN ANALYZE plans.

Parameters:
Return type:

Graph

postbound.vis.plot_join_graph(query_or_join_graph: SqlQuery | JoinGraph, table_annotations: Callable[[TableReference], str] | None = None, *, include_pk_fk_joins: bool = False, out_path: str = '', out_format: str = 'svg') Graph | Digraph#

Creates a Graphviz visualization of a join graph.

The join graph can be either supplied directly (in which case it will be visualized as a directed graph), or implicitly through its SQL query. In this case, the join graph is inferred based on the join conditions. Such a graph can be further customized to also highlight primary-key/foreign-key relationships as a directed graph.

The directed graph variants will point from the foreign key table to the primary key table.

To customize the information shown on each table node, a custom table_annotations function can be provided. Several such functions for common annotations are already provided in this module. Annotation functions have a very simple signature: they take the table currently being rendered as input and return a string containing the metadata to be shown on the node. To add additional context to these methods, it is advisable to use functools.partial to bind additional parameters.

See also

estimated_cards, annotate_filter_cards, annotate_cards, merged_annotation

Parameters:
  • query_or_join_graph (SqlQuery | JoinGraph)

  • table_annotations (Callable[[TableReference], str] | None)

  • include_pk_fk_joins (bool)

  • out_path (str)

  • out_format (str)

Return type:

Graph | Digraph

postbound.vis.plot_join_tree(join_tree: JoinTree) Graph#

Creates a Graphviz visualization of a join tree.

Parameters:

join_tree (JoinTree)

Return type:

Graph

postbound.vis.plot_query_plan(plan: QueryPlan, annotation_generator: Callable[[QueryPlan], str] | None = None, *, skip_intermediates: bool = False, **kwargs) Graph#

Creates a Graphviz visualization of a query plan.

By default, each node is just annotated with its operator type and base table (for scans). To add additional information (e.g., estimated or true cardinality), a custom annotation_generator function can be provided. Such a function takes the current QueryPlan node as input and returns a string containing the metadata to be shown on the node. Since this signature is quite simple, it is advisable to use functools.partial to bind additional parameters to the function. This module already provides the most common annotation function: annotate_estimates, which adds estimated cost and cardinality.

For EXPLAIN ANALYZE plans (i.e. plans containing runtime information), the plot_analyze_plan function has as meaningful default annotation generator.

Parameters:
  • plan (QueryPlan)

  • annotation_generator (Callable[[QueryPlan], str] | None)

  • skip_intermediates (bool)

Return type:

Graph

postbound.vis.plot_relalg(relnode: RelNode, **kwargs) Graph#

Creates a Graphviz visualization of a relational algebra expression tree.

Additional keyword arguments are passed to plot_tree.

Parameters:

relnode (RelNode)

Return type:

Graph

postbound.vis.plot_tree(node: ~postbound._base.T, label_generator: ~collections.abc.Callable[[~postbound._base.T], tuple[str, dict]], child_supplier: ~collections.abc.Callable[[~postbound._base.T], ~collections.abc.Sequence[~postbound._base.T]], *, escape_labels: bool = True, out_path: str = '', out_format: str = 'svg', node_id_generator: ~collections.abc.Callable[[~postbound._base.T], int] = <built-in function hash>, _graph: ~graphviz.graphs.Graph | None = None, **kwargs) Graph#

Transforms an arbitrary tree into a Graphviz graph. The tree traversal is achieved via callback functions.

Start the traversal at the root node.

Parameters:
  • node (T) – The node to plot.

  • label_generator (Callable[[T], tuple[str, dict]]) – Callback function to generate labels of the nodes in the graph. The dictionary can contain additional formatting attributes (e.g. bold font). Consult the Graphviz documentation for allowed values

  • child_supplier (Callable[[T], Sequence[T]]) – Provides the children of the current node.

  • escape_labels (bool, optional) – Whether to escape the labels of the nodes. Defaults to True. If set to False, the labels will be rendered as-is and all HTML-like tags will be interpreted as such.

  • out_path (str, optional) – An optional file path to store the graph at. If empty, the graph will only be provided as a Graphviz object.

  • out_format (str, optional) – The output format of the graph. Defaults to SVG and will only be used if the graph should be stored to disk (according to out_path).

  • node_id_generator (Callable[[T], int], optional) – Callback function to generate unique identifiers for the nodes. Defaults to the hash function of the nodes. These identifiers are only used internally to identify the different nodes in the graph.

  • _graph (Optional[gv.Graph], optional) – Internal parameter used for state-management within the plotting function. Do not set this parameter yourself!

Returns:

_description_

Return type:

gv.Graph

See also

gv.Dot.node, gv.Dot.edge

References

postbound.vis.setup_annotations(*annotations: Literal['estimated-cards', 'filter-cards', 'true-cards'], query: SqlQuery, database: Database | None = None) Callable[[TableReference], str]#

Annotates the nodes of a join graph with different cardinality estimates.

Parameters:
  • annotations (Literal['estimated-cards', 'filter-cards', 'true-cards'])

  • query (SqlQuery)

  • database (Database | None)

Return type:

Callable[[TableReference], str]