Plan Enumeration#

Enumerative optimization strategies provide all possible plans in an exhaustive manner.

These strategies do not make use of any statistics, etc. to generate “good” plans. Instead, they focus on the structure of the plans to generate new plans.

class postbound.opt.enumeration.ExhaustiveJoinOrderEnumerator(tree_structure: Literal['bushy', 'left-deep', 'right-deep'] = 'bushy')#

Utility service to provide all possible join trees for an input query.

The service produces a generator that in turn provides the join orders. This is done in the all_join_orders_for method. The provided join orders can include linear as well as bushy join orders. This can be customized during service creation.

Parameters:

tree_structure (Literal[bushy, left-deep, right-deep], optional) – The kind of join orders that are generated by the service. “bushy” allows join orders with arbitrary branches to be generated (including linear join orders). “right-deep” and “left-deep” restrict the join orders to the respective linear trees. Defaults to “bushy”.

Warning

For now, the underlying algorithm is limited to queries without cross-products.

all_join_orders_for(query: SqlQuery) Generator[JoinTree, None, None]#

Produces a generator for all possible join trees of a query.

Parameters:

query (SqlQuery) – The query to “optimize”

Yields:

Generator[JoinTree] – A generator that produces all possible join orders for the input query. The structure of the join orders depends on the service configuration. Consult the class-level documentation for details.

Raises:

ValueError – If the query contains cross products.

Return type:

Generator[JoinTree, None, None]

Warning

For now, the underlying algorithm is limited to queries without cross-products.

class postbound.opt.enumeration.ExhaustiveOperatorEnumerator(scan_operators: Iterable[ScanOperator] | None = None, join_operators: Iterable[JoinOperator] | None = None, *, include_scans: bool = True, include_joins: bool = True, database: Database | None = None)#

Utility service to generate all possible assignments of physical operators for a join order.

The service produces a generator that in turn provides the operator assignments. This is done in the all_operator_assignments_for method. The precise properties of the generated assignments depends on the configuration of this service. It can be set up to only use a subset of the available operators or to exclude operators for scans or joins completely. By default, the service uses all operators that are supported by the target database system.

Parameters:
  • scan_operators (Optional[Iterable[ScanOperators]], optional) – The scan operators that can be used in the query plans. If this is None or empty, all scans supported by the database are used. Likewise, if the iterable contains an operator that is not supported by the database, it is exlcuded from generation.

  • join_operators (Optional[Iterable[JoinOperators]], optional) – The join operators that can be used in the query plans. If this is None or empty, all joins supported by the database are used. Likewise, if the iterable contains an operator that is not supported by the database, it is exlcuded from generation.

  • include_scans (bool, optional) – Whether the assignment should contain scan operators at all. By default, this is enabled. However, if scans are disabled, this overwrites any supplied operators in the scan_operators parameter.

  • include_joins (bool, optional) – Whether the assignment should contain join operators at all. By default, this is enabled. However, if joins are disabled, this overwrites any supplied operators in the join_operators parameter.

  • database (Optional[db.Database], optional) – The database that should execute the queries in the end. The database connection is necessary to determine the operators that are actually supported by the system. If this parameter is omitted, it is inferred from the DatabasePool.

Raises:

ValueError – If both scans and joins are disabled

all_operator_assignments_for(query: SqlQuery, join_order: JoinTree) Generator[PhysicalOperatorAssignment, None, None]#

Produces a generator for all possible operator assignments of the allowed operators.

The precise structure of the operator assignments depends on the service configuration. Take a look at the class documentation for details.

Parameters:
  • query (SqlQuery) – The query to “optimize”

  • join_order (JoinTree) – The join sequence to use. This contains all required tables to be scanned and joins to be performed.

Yields:

Generator[PhysicalOperatorAssignment, None, None] – A generator producing all possible operator assignments. The assignments will not contain any cost estimates, nor will they specify join directions or parallization data.

Return type:

Generator[PhysicalOperatorAssignment, None, None]

class postbound.opt.enumeration.ExhaustivePlanEnumerator(*, join_order_args: dict | None = None, operator_args: dict | None = None)#

Utility service to provide all possible exection plans for a query.

This service combines the ExhaustiveJoinOrderEnumerator and ExhaustiveOperatorEnumerator into a single high-level service. Therefore, it underlies the same restrictions as these two services. The produced generator can be accessed via the all_plans_for method.

Parameters:
  • join_order_args (Optional[dict], optional) – Configuration for the ExhaustiveJoinOrderEnumerator. This is forwarded to the service’s __init__ method.

  • operator_args (Optional[dict], optional) – Configuration for the ExhaustiveOperatorEnumerator. This is forwarded to the service’s __init__ method.

all_plans_for(query: SqlQuery) Generator[QueryPlan, None, None]#

Produces a generator for all possible query plans of an input query.

The structure of the provided plans can be restricted by configuring the underlying services. Consult the class-level documentation for details.

Parameters:

query (SqlQuery) – The query to “optimize”

Yields:

Generator[QueryPlan, None, None] – A generator producing all possible query plans

Return type:

Generator[QueryPlan, None, None]