Обсуждение: Add a greedy join search algorithm to handle large join problems
Hi hackers,
This patch implements GOO (Greedy Operator Ordering), a greedy
join-order search method for large join problems, based on Fegaras (DEXA
’98) [1]. The algorithm repeatedly selects, among all legal joins, the
join pair with the lowest estimated total cost, merges them, and
continues until a single join remains. Patch attached.
To get an initial sense of performance, I reused the star join /
snowflake examples and the testing script from the thread in [2]. The
star-join GUC in that SQL workload was replaced with
`enable_goo_join_search`, so the same tests can run under DP (standard
dynamic programming) / GEQO(Genetic Query Optimizer) / GOO. For these
tests, geqo_threshold was set to 15 for DP, and to 5 for both GEQO and
GOO. Other planner settings, including join_collapse_limit, remained at
their defaults.
On my local machine, a single-client pgbench run produces the following
throughput (tps):
| DP | GEQO | GOO
--------------------+----------+----------+-----------
starjoin (inner) | 1762.52 | 192.13 | 6168.89
starjoin (outer) | 1683.92 | 173.90 | 5626.56
snowflake (inner) | 1829.04 | 133.40 | 3929.57
snowflake (outer) | 1397.93 | 99.65 | 3040.52
Open questions:
* The paper ranks joins by estimated result size, while this prototype
reuses the existing planner total_cost. This makes the implementation
straightforward, but it may be worth exploring row-based rule.
* The prototype allocates through multiple memory contexts, aiming to
reduce memory usage during candidate evaluation. Suggestions on
simplification are welcome.
* Planning performance vs GEQO: On the star/snowflake benchmarks above,
GOO reduces planning time significantly compared to GEQO. Broader
evaluation on more representative workloads (e.g., TPC-H / TPC-DS /
JOB) is TODO, covering both planning speed and plan quality.
* There is no tuning knob like `geqo_seed` for GEQO if GOO produces a
poor ordering.
* The long-term integration is open:
* fully replace GEQO,
* keep GEQO available and optionally try both,
* or use GOO as a starting point for GEQO.
Comments and review would be appreciated.
References:
[1] Leonidas Fegaras, “A New Heuristic for Optimizing Large Queries”,
DEXA ’98. ACM Digital Library:
https://dl.acm.org/doi/10.5555/648311.754892 A publicly accessible
PostScript version is available from the author's page:
https://lambda.uta.edu/order.ps
[2] Star/snowflake join thread and benchmarks:
https://www.postgresql.org/message-id/a22ec6e0-92ae-43e7-85c1-587df2a65f51%40vondra.me
This patch implements GOO (Greedy Operator Ordering), a greedy
join-order search method for large join problems, based on Fegaras (DEXA
’98) [1]. The algorithm repeatedly selects, among all legal joins, the
join pair with the lowest estimated total cost, merges them, and
continues until a single join remains. Patch attached.
To get an initial sense of performance, I reused the star join /
snowflake examples and the testing script from the thread in [2]. The
star-join GUC in that SQL workload was replaced with
`enable_goo_join_search`, so the same tests can run under DP (standard
dynamic programming) / GEQO(Genetic Query Optimizer) / GOO. For these
tests, geqo_threshold was set to 15 for DP, and to 5 for both GEQO and
GOO. Other planner settings, including join_collapse_limit, remained at
their defaults.
On my local machine, a single-client pgbench run produces the following
throughput (tps):
| DP | GEQO | GOO
--------------------+----------+----------+-----------
starjoin (inner) | 1762.52 | 192.13 | 6168.89
starjoin (outer) | 1683.92 | 173.90 | 5626.56
snowflake (inner) | 1829.04 | 133.40 | 3929.57
snowflake (outer) | 1397.93 | 99.65 | 3040.52
Open questions:
* The paper ranks joins by estimated result size, while this prototype
reuses the existing planner total_cost. This makes the implementation
straightforward, but it may be worth exploring row-based rule.
* The prototype allocates through multiple memory contexts, aiming to
reduce memory usage during candidate evaluation. Suggestions on
simplification are welcome.
* Planning performance vs GEQO: On the star/snowflake benchmarks above,
GOO reduces planning time significantly compared to GEQO. Broader
evaluation on more representative workloads (e.g., TPC-H / TPC-DS /
JOB) is TODO, covering both planning speed and plan quality.
* There is no tuning knob like `geqo_seed` for GEQO if GOO produces a
poor ordering.
* The long-term integration is open:
* fully replace GEQO,
* keep GEQO available and optionally try both,
* or use GOO as a starting point for GEQO.
Comments and review would be appreciated.
References:
[1] Leonidas Fegaras, “A New Heuristic for Optimizing Large Queries”,
DEXA ’98. ACM Digital Library:
https://dl.acm.org/doi/10.5555/648311.754892 A publicly accessible
PostScript version is available from the author's page:
https://lambda.uta.edu/order.ps
[2] Star/snowflake join thread and benchmarks:
https://www.postgresql.org/message-id/a22ec6e0-92ae-43e7-85c1-587df2a65f51%40vondra.me
--
Best regards,
Chengpeng Yan
Вложения
On Tue, Dec 2, 2025 at 9:18 AM Chengpeng Yan <chengpeng_yan@outlook.com> wrote: > > Hi hackers, > > This patch implements GOO (Greedy Operator Ordering), a greedy > join-order search method for large join problems, based on Fegaras (DEXA > ’98) [1]. The algorithm repeatedly selects, among all legal joins, the > join pair with the lowest estimated total cost, merges them, and > continues until a single join remains. Patch attached. Interesting. > To get an initial sense of performance, I reused the star join / > snowflake examples and the testing script from the thread in [2]. The > star-join GUC in that SQL workload was replaced with > `enable_goo_join_search`, so the same tests can run under DP (standard > dynamic programming) / GEQO(Genetic Query Optimizer) / GOO. For these > tests, geqo_threshold was set to 15 for DP, and to 5 for both GEQO and > GOO. Other planner settings, including join_collapse_limit, remained at > their defaults. > > On my local machine, a single-client pgbench run produces the following > throughput (tps): > > | DP | GEQO | GOO > --------------------+----------+----------+----------- > starjoin (inner) | 1762.52 | 192.13 | 6168.89 > starjoin (outer) | 1683.92 | 173.90 | 5626.56 > snowflake (inner) | 1829.04 | 133.40 | 3929.57 > snowflake (outer) | 1397.93 | 99.65 | 3040.52 > Is pgbench the right workload to test this, I mean what are we trying to compare here the planning time taken by DP vs GEQO vs GOO or the quality of the plans generated by different join ordering algorithms or both? All pgbench queries are single table scans and there is no involvement of the join search, so I am not sure how we can justify these gains? -- Regards, Dilip Kumar Google
Hi, Thanks for taking a look. > On Dec 2, 2025, at 13:36, Dilip Kumar <dilipbalaut@gmail.com> wrote: > > Is pgbench the right workload to test this, I mean what are we trying > to compare here the planning time taken by DP vs GEQO vs GOO or the > quality of the plans generated by different join ordering algorithms > or both? All pgbench queries are single table scans and there is no > involvement of the join search, so I am not sure how we can justify > these gains? Just to clarify: as noted in the cover mail, the numbers are not from default pgbench queries, but from the star-join / snowflake workloads in thread [1], using the benchmark included in the v5-0001 patch. These workloads contain multi-table joins and do trigger join search; you can reproduce them by configuring the GUCs as described in the cover mail. The benchmark tables contain no data, so execution time is negligible; the results mainly reflect planning time of the different join-ordering methods, which is intentional for this microbenchmark. A broader evaluation on TPC-H / TPC-DS / JOB is TODO, covering both planning time and plan quality. That should provide a more representative picture of GOO, beyond this synthetic setup. References: [1] Star/snowflake join thread and benchmarks: https://www.postgresql.org/message-id/a22ec6e0-92ae-43e7-85c1-587df2a65f51%40vondra.me -- Best regards, Chengpeng Yan
On 12/2/25 04:48, Chengpeng Yan wrote: > Hi hackers, > > This patch implements GOO (Greedy Operator Ordering), a greedy > join-order search method for large join problems, based on Fegaras (DEXA > ’98) [1]. The algorithm repeatedly selects, among all legal joins, the > join pair with the lowest estimated total cost, merges them, and > continues until a single join remains. Patch attached. > > To get an initial sense of performance, I reused the star join / > snowflake examples and the testing script from the thread in [2]. The > star-join GUC in that SQL workload was replaced with > `enable_goo_join_search`, so the same tests can run under DP (standard > dynamic programming) / GEQO(Genetic Query Optimizer) / GOO. For these > tests, geqo_threshold was set to 15 for DP, and to 5 for both GEQO and > GOO. Other planner settings, including join_collapse_limit, remained at > their defaults. > > On my local machine, a single-client pgbench run produces the following > throughput (tps): > > | DP | GEQO | GOO > --------------------+----------+----------+----------- > starjoin (inner) | 1762.52 | 192.13 | 6168.89 > starjoin (outer) | 1683.92 | 173.90 | 5626.56 > snowflake (inner) | 1829.04 | 133.40 | 3929.57 > snowflake (outer) | 1397.93 | 99.65 | 3040.52 > Seems interesting, and also much more ambitious than what I intended to do in the starjoin thread (which is meant to be just a simplistic heuristics on top of the regular join order planning). I think a much broader evaluation will be needed, comparing not just the planning time, but also the quality of the final plan. Which for the starjoin tests does not really matter, as the plans are all equal in this regard. regards -- Tomas Vondra
Hi, > On Dec 2, 2025, at 18:56, Tomas Vondra <tomas@vondra.me> wrote: > > I think a much broader evaluation will be needed, comparing not just the > planning time, but also the quality of the final plan. Which for the > starjoin tests does not really matter, as the plans are all equal in > this regard. Many thanks for your feedback. You are absolutely right — plan quality is also very important. In my initial email I only showed the improvements in planning time, but did not provide results regarding plan quality. I will run tests on more complex join scenarios, evaluating both planning time and plan quality. Thanks again! -- Best regards, Chengpeng Yan