该GEQO模块将查询优化问题视为众所周知的旅行商问题 (TSP). 可能的查询计划被编码为整数字符串。每个字符串表示从查询的一个关系到下一个关系的连接顺序。例如,连接树
/\ /\ 2 /\ 3 4 1
由整数字符串“4-1-3-2”编码,这意味着首先连接关系“4”和“1”,然后是“3”,然后是“2”,其中 1、2、3、4 是 PostgreSQL 优化器中的关系 ID。
该GEQO在 PostgreSQL 中的实现的具体特征是
使用稳态GA(替换种群中适应性最差的个体,而不是整代替换) 允许快速收敛到改进的查询计划。这对于在合理时间内处理查询至关重要;
使用边缘重组交叉,这特别适合于保持边缘损失对于解决TSP通过GA;
突变作为遗传算子已被弃用,因此不需要修复机制来生成合法的TSP路径。
该GEQO模块的部分内容改编自 D. Whitley 的 Genitor 算法。
该GEQO模块允许 PostgreSQL 查询优化器通过非穷举搜索有效地支持大型连接查询。
该GEQO计划过程使用标准计划程序代码生成单个关系扫描的计划。然后使用遗传方法开发连接计划。如上所示,每个候选连接计划都由一个连接基本关系的顺序表示。在初始阶段,GEQO代码只是随机生成一些可能的连接序列。对于每个考虑的连接序列,都会调用标准计划程序代码来估计使用该连接序列执行查询的成本。(对于连接序列的每个步骤,都会考虑所有三种可能的连接策略;并且所有最初确定的关系扫描计划都可用。估计成本是这些可能性中最便宜的。)估计成本较低的连接序列被认为比成本较高的连接序列“更适合”。遗传算法会丢弃适应性最差的候选者。然后通过组合适应性更强的候选者的基因来生成新的候选者——也就是说,使用已知低成本连接序列的随机选择的片段来创建新的序列以供考虑。重复此过程,直到考虑了预设数量的连接序列;然后在搜索期间任何时间找到的最佳连接序列用于生成最终计划。
此过程本质上是非确定性的,因为在初始种群选择和随后对最佳候选者的“突变”过程中都进行了随机选择。为了避免所选计划发生意外变化,GEQO 算法的每次运行都会使用当前的 geqo_seed 参数设置重新启动其随机数生成器。只要geqo_seed
和其他 GEQO 参数保持固定,对于给定的查询(以及其他计划程序输入,如统计信息),将生成相同的计划。要试验不同的搜索路径,请尝试更改geqo_seed
。
仍然需要改进遗传算法参数设置。在文件src/backend/optimizer/geqo/geqo_main.c
中,例程gimme_pool_size
和gimme_number_generations
,我们必须找到参数设置的折衷方案以满足两个相互竞争的需求
查询计划的最优性
计算时间
在当前实现中,每个候选连接序列的适应度是通过从头开始运行标准计划程序的连接选择和成本估算代码来估计的。在不同候选者使用类似的连接子序列的范围内,将重复大量工作。通过保留子连接的成本估计,可以使这部分工作速度显著加快。问题在于避免在保留该状态上花费过多的内存。
在更基本的层面上,目前尚不清楚使用为 TSP 设计的 GA 算法解决查询优化是否合适。在 TSP 案例中,与任何子字符串(部分路径)相关的成本独立于路径的其余部分,但这对于查询优化肯定不是真的。因此,边缘重组交叉是否是最高效的突变过程值得怀疑。
如果您在文档中看到任何不正确的内容,与您对特定功能的体验不符,或者需要进一步澄清,请使用此表单报告文档问题。