PostgreSQL 中文参考文档
🌐 英文原版 官方 ↗

61.3. PostgreSQL 中的遗传查询优化 #

61.3.1. 利用 GEQO 生成候选计划
61.3.2. PostgreSQL GEQO 的未来实现工作

GEQO 模块将查询优化问题当作著名的旅行商问题 (TSP)来处理。可能的查询计划被编码为整数字符串, 每个字符串表示从一个关系到下一个关系的连接顺序。例如,连接树

   /\
  /\ 2
 /\ 3
4  1

被编码为整数字符串 '4-1-3-2',意思是先连接关系 '4' 和 '1',然后连接 '3',再连接 '2',其中 1、2、3、4 是 PostgreSQL 优化器中的关系 ID。

PostgreSQL 中 GEQO 实现的具体特点包括:

GEQO 模块的部分内容改编自 D. Whitley 的 Genitor 算法。

GEQO 模块使 PostgreSQL 查询优化器能够通过非穷举搜索有效地支持大型连接查询。

61.3.1. 利用 GEQO 生成候选计划 #

GEQO 的规划过程使用标准规划器代码为各个关系的扫描 生成计划,然后用遗传方法构造连接计划。如上所示,每个候选连接计划由 一个连接基础关系的顺序表示。在初始阶段,GEQO 代码 只是随机生成一些可能的连接顺序。对于考虑中的每个连接顺序,都会调用 标准规划器代码来估算按该顺序执行查询的代价。(对于连接顺序的每一步, 三种可能的连接策略都会被考虑;并且最初确定的所有关系扫描计划都可用。 估算的代价取这些可能性中最便宜的一种。)估算代价较低的连接顺序被视为 比代价较高的连接顺序“更适应”。遗传算法会丢弃适应度最低的 候选者。然后,通过组合较优候选者的基因来生成新的候选者,即利用从已知 低代价连接序列中随机选取的部分来构造待考虑的新序列。这一过程不断重复, 直到预设数量的连接顺序都被考虑过;随后使用搜索过程中任一时刻找到的 最优者来生成最终计划。

由于初始种群选择以及后续对最优候选者的“变异”都存在随机 选择,这一过程本质上是不确定的。为了避免所选计划出现令人意外的变化, GEQO 算法的每次运行都会用当前的 geqo_seed 参数 设置重新初始化其随机数生成器。只要 geqo_seed 和其他 GEQO 参数保持固定,对于给定的查询(以及其他规划器输入,如统计信息), 将生成相同的计划。要尝试不同的搜索路径,可以试着修改 geqo_seed。

61.3.2. PostgreSQL GEQO 的未来实现工作 #

遗传算法参数设置仍有待改进。在文件 src/backend/optimizer/geqo/geqo_main.c 中, 例程 gimme_pool_size 和 gimme_number_generations 必须在参数设置上做出折中,以满足两个相互冲突的需求:

  • 查询计划的最优性

  • 计算时间

在当前的实现中,每个候选连接顺序的适应度是通过从头运行标准规划器的 连接选择和代价估算代码来评估的。由于不同的候选者往往使用相似的连接 子序列,大量工作会被重复进行。如果保留子连接的代价估算结果,速度可以 显著提升。问题在于如何避免为保留这些状态而耗费不合理的内存。

从更根本的层面看,用为 TSP 设计的 GA 算法来求解查询优化是否合适尚 不明确。在 TSP 中,任何子串(部分路径)的代价与路径的其余部分无关, 但对查询优化而言这肯定不成立。因此,边重组交叉是否是最有效的变异 过程也值得怀疑。