mirror of
https://github.com/hanzoai/postgres.git
synced 2026-10-30 18:33:07 +00:00
Provide a facility that (1) can be used to stabilize certain plan choices so that the planner cannot reverse course without authorization and (2) can be used by knowledgeable users to insist on plan choices contrary to what the planner believes best. In both cases, terrible outcomes are possible: users should think twice and perhaps three times before constraining the planner's ability to do as it thinks best; nevertheless, there are problems that are much more easily solved with these facilities than without them. This patch takes the approach of analyzing a finished plan to produce textual output, which we call "plan advice", that describes key decisions made during plan; if that plan advice is provided during future planning cycles, it will force those key decisions to be made in the same way. Not all planner decisions can be controlled using advice; for example, decisions about how to perform aggregation are currently out of scope, as is choice of sort order. Plan advice can also be edited by the user, or even written from scratch in simple cases, making it possible to generate outcomes that the planner would not have produced. Partial advice can be provided to control some planner outcomes but not others. Currently, plan advice is focused only on specific outcomes, such as the choice to use a sequential scan for a particular relation, and not on estimates that might contribute to those outcomes, such as a possibly-incorrect selectivity estimate. While it would be useful to users to be able to provide plan advice that affects selectivity estimates or other aspects of costing, that is out of scope for this commit. Reviewed-by: Lukas Fittl <[email protected]> Reviewed-by: Jakub Wartak <[email protected]> Reviewed-by: Greg Burd <[email protected]> Reviewed-by: Jacob Champion <[email protected]> Reviewed-by: Haibo Yan <[email protected]> Reviewed-by: Dian Fay <[email protected]> Reviewed-by: Ajay Pal <[email protected]> Reviewed-by: John Naylor <[email protected]> Reviewed-by: Alexandra Wang <[email protected]> Discussion: http://postgr.es/m/CA+TgmoZ-Jh1T6QyWoCODMVQdhTUPYkaZjWztzP1En4=ZHoKPzw@mail.gmail.com
86 lines
2.9 KiB
C
86 lines
2.9 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* pgpa_scan.h
|
|
* analysis of scans in Plan trees
|
|
*
|
|
* For purposes of this module, a "scan" includes (1) single plan nodes that
|
|
* scan multiple RTIs, such as a degenerate Result node that replaces what
|
|
* would otherwise have been a join, and (2) Append and MergeAppend nodes
|
|
* implementing a partitionwise scan or a partitionwise join. Said
|
|
* differently, scans are the leaves of the join tree for a single join
|
|
* problem.
|
|
*
|
|
* Copyright (c) 2016-2026, PostgreSQL Global Development Group
|
|
*
|
|
* contrib/pg_plan_advice/pgpa_scan.h
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
#ifndef PGPA_SCAN_H
|
|
#define PGPA_SCAN_H
|
|
|
|
#include "nodes/plannodes.h"
|
|
|
|
typedef struct pgpa_plan_walker_context pgpa_plan_walker_context;
|
|
|
|
/*
|
|
* Scan strategies.
|
|
*
|
|
* PGPA_SCAN_ORDINARY is any scan strategy that isn't interesting to us
|
|
* because there is no meaningful planner decision involved. For example,
|
|
* the only way to scan a subquery is a SubqueryScan, and the only way to
|
|
* scan a VALUES construct is a ValuesScan. We need not care exactly which
|
|
* type of planner node was used in such cases, because the same thing will
|
|
* happen when replanning.
|
|
*
|
|
* PGPA_SCAN_ORDINARY also includes Result nodes that correspond to scans
|
|
* or even joins that are proved empty. We don't know whether or not the scan
|
|
* or join will still be provably empty at replanning time, but if it is,
|
|
* then no scan-type advice is needed, and if it's not, we can't recommend
|
|
* a scan type based on the current plan.
|
|
*
|
|
* PGPA_SCAN_PARTITIONWISE also lumps together scans and joins: this can
|
|
* be either a partitionwise scan of a partitioned table or a partitionwise
|
|
* join between several partitioned tables. Note that all decisions about
|
|
* whether or not to use partitionwise join are meaningful: no matter what
|
|
* we decided this time, we could do more or fewer things partitionwise the
|
|
* next time.
|
|
*
|
|
* PGPA_SCAN_FOREIGN is only used when there's more than one relation involved;
|
|
* a single-table foreign scan is classified as ordinary, since there is no
|
|
* decision to make in that case.
|
|
*
|
|
* Other scan strategies map one-to-one to plan nodes.
|
|
*/
|
|
typedef enum
|
|
{
|
|
PGPA_SCAN_ORDINARY = 0,
|
|
PGPA_SCAN_SEQ,
|
|
PGPA_SCAN_BITMAP_HEAP,
|
|
PGPA_SCAN_FOREIGN,
|
|
PGPA_SCAN_INDEX,
|
|
PGPA_SCAN_INDEX_ONLY,
|
|
PGPA_SCAN_PARTITIONWISE,
|
|
PGPA_SCAN_TID
|
|
/* update NUM_PGPA_SCAN_STRATEGY if you add anything here */
|
|
} pgpa_scan_strategy;
|
|
|
|
#define NUM_PGPA_SCAN_STRATEGY ((int) PGPA_SCAN_TID + 1)
|
|
|
|
/*
|
|
* All of the details we need regarding a scan.
|
|
*/
|
|
typedef struct pgpa_scan
|
|
{
|
|
Plan *plan;
|
|
pgpa_scan_strategy strategy;
|
|
Bitmapset *relids;
|
|
} pgpa_scan;
|
|
|
|
extern pgpa_scan *pgpa_build_scan(pgpa_plan_walker_context *walker, Plan *plan,
|
|
ElidedNode *elided_node,
|
|
bool beneath_any_gather,
|
|
bool within_join_problem);
|
|
|
|
#endif
|