GEQO 是什么,POSTGRESQL SQL优化核心原理为什么在这里
❝开头还是介绍一下群,如果感兴趣PolarDB ,MongoDB ,MySQL ,PostgreSQL ,Redis, OceanBase, Sql Server等有问题,有需求都可以加群加群请联系 liuaustin3 ,(共3400人左右 1 + 2 + 3 + 4 +5 + 6 + 7 + 8 )(1 2 3 4 5 6 7 8群已经爆满 9群 为纯聊天群,默认不加入不得发广告,自己公众号文章链接等,发一次直接踢,默认加入8群,开10群PolarDB专业学习群115+)
上期咱们说到GEQO ,什么是GEQO,geqo_threshold 是 PostgreSQL 配置文件(postgresql.conf)中的一个 GUC(全局统一配置)参数。它的默认值通常是 12。
参数的作用与逻辑
控制优化器策略开关:当查询中的 JOIN 表数量小于 geqo_threshold 时,优化器会采用穷举/动态规划算法(Dynamic Programming)来搜索最优的执行计划;当 JOIN 表数量大于等于 geqo_threshold 时,优化器会自动切换为遗传算法(GEQO,Genetic Query Optimizer),以防止因表数量过多导致优化阶段耗时爆炸。
在源码中的定义位置:
定义与声明:src/backend/utils/misc/guc_tables.c(属于 GUC 参数配置表中的 ConfigureNamesInt 数组)。
算法切换逻辑应用:src/backend/optimizer/plan/planner.c 里的 make_one_rel 函数(在此处通过判断 JOIN 关系的层级/表数量是否达到了 geqo_threshold,来决定调用 standard_join_search 还是 geqo)。
修改方法:
全局修改:编辑 postgresql.conf,将 geqo_threshold = 12 改为你需要的值,然后执行 SELECT pg_reload_conf();。
看到这里,作为PG ACE我竟然这块的知识没有接触过,真是罪过,罪过
下面我好好地把这些参数捋一捋
geqo
含义:是否启用 GEQO(遗传算法优化器)
on:强制启用 GEQO
off:强制禁用 GEQO
默认:auto(根据 geqo_threshold 自动触发)
作用场景:
当你想强制测试 GEQO 行为时使用,例如构造 12+ JOIN 的实验。
geqo_threshold
含义:JOIN 表数量 ≥ 该值时启用 GEQO
默认:12
典型范围:12–24
影响:
设置低了 → 普通查询也用 GEQO,计划质量下降
设置高了 → 复杂 JOIN 仍用 DP,规划时间爆炸
geqo_effort
含义:搜索强度(1–10),决定 GEQO 的整体计算量
默认:5
越大 → 搜索更充分 → 计划质量更好,但规划时间更长
越小 → 搜索更快,但可能找不到好计划
影响的内部参数:
geqo_pool_size(种群大小)
geqo_generations(迭代次数)
这两个如果设为 0,会根据 geqo_effort 自动计算。
geqo_pool_size
含义:种群大小(population size)
默认:0 → 自动根据 geqo_effort 计算
典型范围:50–200
影响:
大种群 → 搜索空间更大 → 计划质量更好 → 规划更慢
小种群 → 搜索空间小 → 速度快但质量差
内部公式(简化):
Code
pool_size ≈ geqo_effort × log(n_tables)
geqo_generations
含义:遗传算法迭代次数(generation count)
默认:0 → 自动根据 geqo_effort 计算
典型范围:100–500
影响:
迭代越多 → 越可能找到更优 JOIN 顺序
迭代太少 → 搜索不充分,计划质量下降
内部公式(简化):
Code
generations ≈ geqo_effort × pool_size
geqo_selection_bias
含义:选择偏置(selection bias),控制“优秀个体”被选中的概率
默认:2.0
范围:1.5–2.0
解释:
越接近 2.0 → 更偏向选择适应度高的个体(更贪心)
越接近 1.5 → 更均匀选择(更随机)
影响:
偏置高 → 更快收敛,但可能陷入局部最优
偏置低 → 搜索更广,但收敛慢
geqo_seed
含义:遗传算法随机种子(0.0 = 使用系统随机)
默认:0.0
设置为固定值(如 1.0)可让 GEQO 结果可复现
用途: 用于实验、调试、论文复现 JOIN 顺序。
好,既然是没有怎么接触过,我们的做个实验,不过今天有点晚了,我先把实验的步骤写清楚,下期咱们做做实验
1 建立测试表
-- 1. 创建 8 张测试表
CREATE TABLE t1 (id int PRIMARY KEY, val int);
CREATE TABLE t2 (id int PRIMARY KEY, val int);
CREATE TABLE t3 (id int PRIMARY KEY, val int);
CREATE TABLE t4 (id int PRIMARY KEY, val int);
CREATE TABLE t5 (id int PRIMARY KEY, val int);
CREATE TABLE t6 (id int PRIMARY KEY, val int);
CREATE TABLE t7 (id int PRIMARY KEY, val int);
CREATE TABLE t8 (id int PRIMARY KEY, val int);
-- 2. 插入少量数据并更新统计信息
INSERT INTO t1 SELECT g, g % 10 FROM generate_series(1, 1000) g;
INSERT INTO t2 SELECT g, g % 10 FROM generate_series(1, 1000) g;
INSERT INTO t3 SELECT g, g % 10 FROM generate_series(1, 1000) g;
INSERT INTO t4 SELECT g, g % 10 FROM generate_series(1, 1000) g;
INSERT INTO t5 SELECT g, g % 10 FROM generate_series(1, 1000) g;
INSERT INTO t6 SELECT g, g % 10 FROM generate_series(1, 1000) g;
INSERT INTO t7 SELECT g, g % 10 FROM generate_series(1, 1000) g;
INSERT INTO t8 SELECT g, g % 10 FROM generate_series(1, 1000) g;
ANALYZE;
在默认配置下,8 张表远小于 geqo_threshold = 12,因此优化器会使用传统的穷举/动态规划算法。
SQL
-- 关闭 GEQO,使用标准动态规划(DP)
SET geqo = off;
-- 查看优化器生成的执行计划与耗时(注意查看 Planning Time)
EXPLAIN (ANALYZE, COSTS ON)
SELECT *
FROM t1
JOIN t2 ON t1.val = t2.val
JOIN t3 ON t2.val = t3.val
JOIN t4 ON t3.val = t4.val
JOIN t5 ON t4.val = t5.val
JOIN t6 ON t5.val = t6.val
JOIN t7 ON t6.val = t7.val
JOIN t8 ON t7.val = t8.val
WHERE t1.id = 1;
-- 1. 强制启用 GEQO 并降低触发阈值
SET geqo = on;
SET geqo_threshold = 6; -- 8张表 >= 6,强行进入 GEQO 流程
-- 2. 配置 GEQO 运行参数(可选,用于观察控制效果)
SET geqo_pool_size = 50; -- 种群大小:50个个体
SET geqo_effort = 5; -- 搜索强度:控制迭代代数
SET geqo_seed = 0.5; -- 固定的随机种子(保证实验可重复)
-- 3. 执行相同的 EXPLAIN,观察执行计划
EXPLAIN (ANALYZE, COSTS ON)
SELECT *
FROM t1
JOIN t2 ON t1.val = t2.val
JOIN t3 ON t2.val = t3.val
JOIN t4 ON t4.val = t3.val
JOIN t5 ON t4.val = t5.val
JOIN t6 ON t5.val = t6.val
JOIN t7 ON t6.val = t7.val
JOIN t8 ON t7.val = t8.val
WHERE t1.id = 1;
-- 改变随机种子,让 GEQO 重新进行种群演化
SET geqo_seed = 0.9;
EXPLAIN (COSTS ON)
SELECT *
FROM t1
JOIN t2 ON t1.val = t2.val
JOIN t3 ON t2.val = t3.val
JOIN t4 ON t3.val = t4.val
JOIN t5 ON t4.val = t5.val
JOIN t6 ON t5.val = t6.val
JOIN t7 ON t6.val = t7.val
JOIN t8 ON t7.val = t8.val
WHERE t1.id = 1;
好了,今天就到这,下期我们把测试的结果拿出来看看GEQO的参数调整和PG的数据库优化之间的关系