支持的版本: 当前 (17) / 16 / 15 / 14 / 13
开发版本: devel
不支持的版本: 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2 / 7.1

60.3. 遗传查询优化 (GEQO) 在 PostgreSQL 中 #

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

   /\
  /\ 2
 /\ 3
4  1

被编码为整数字符串“4-1-3-2”,这意味着首先连接关系“4”和“1”,然后是“3”,然后是“2”,其中 1、2、3、4 是 PostgreSQL 优化器内的关系 ID。

PostgreSQL 中的GEQO实现的具体特点是

  • 使用稳态GA(替换种群中最不适应的个体,而不是整代替换) 可以快速收敛到改进的查询计划。这对于在合理的时间内处理查询至关重要;

  • 使用边缘重组交叉,特别适合通过TSP来保持GA;

  • 边缘损失较低的解决方案。突变作为遗传算子已被弃用,因此不需要修复机制来生成合法的TSP路径。

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

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

60.3.1. 使用 GEQO 生成可能的计划GEQO #

GEQO计划过程使用标准计划器代码为单个关系的扫描生成计划。然后使用遗传方法开发连接计划。如上所示,每个候选连接计划都由一个序列表示,在该序列中连接基本关系。在初始阶段,GEQO代码只是随机生成一些可能的连接序列。对于考虑的每个连接序列,都会调用标准计划器代码来估计使用该连接序列执行查询的成本。(对于连接序列的每一步,都会考虑所有三种可能的连接策略;并且所有最初确定的关系扫描计划都可用。估计成本是这些可能性中最便宜的。) 估计成本较低的连接序列被认为比成本较高的连接序列“更适应”。遗传算法会丢弃最不适应的候选者。然后,通过组合更适应的候选者的基因来生成新的候选者,也就是说,通过使用已知低成本连接序列的随机选择部分来创建新的序列以供考虑。重复此过程,直到考虑了预设数量的连接序列;然后使用在搜索期间任何时候找到的最佳序列来生成完成的计划。

此过程本质上是不确定的,因为在初始种群选择和后续最佳候选者的“突变”过程中都做出了随机选择。为了避免所选计划出现令人惊讶的更改,GEQO 算法的每次运行都会使用当前的 geqo_seed 参数设置重新启动其随机数生成器。只要 geqo_seed 和其他 GEQO 参数保持固定,就会为给定的查询(以及其他计划器输入,例如统计信息)生成相同的计划。要尝试不同的搜索路径,请尝试更改 geqo_seed

60.3.2. PostgreSQL 的未来实现任务GEQO #

仍需要工作来改进遗传算法参数设置。在文件 src/backend/optimizer/geqo/geqo_main.c 中,例程 gimme_pool_sizegimme_number_generations,我们必须找到参数设置的折衷方案,以满足两个相互竞争的需求

  • 查询计划的最优性

  • 计算时间

在当前的实现中,每个候选连接序列的适应度是通过从头开始运行标准计划器的连接选择和成本估计代码来估计的。在不同候选者使用相似的连接子序列的程度上,将重复大量工作。通过保留子连接的成本估计,可以使其明显更快。问题在于避免在保留该状态上花费不合理的内存量。

在更基本的层面上,尚不清楚是否适合使用为 TSP 设计的 GA 算法来解决查询优化。在 TSP 案例中,与任何子字符串(部分路径)关联的成本与路径的其余部分无关,但这对于查询优化来说肯定不是真的。因此,边缘重组交叉是否是最有效的突变程序值得怀疑。

提交更正

如果您在文档中发现任何不正确、与您使用特定功能的经验不符或需要进一步澄清的内容,请使用 此表单 报告文档问题。