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

19.7. 查询规划优化器参数 #

19.7.1. 规划器方法开关配置
19.7.2. 优化器代价计算常数
19.7.3. 遗传算法优化器
19.7.4. 其他优化器选项

19.7.1. 规划器方法开关配置 #

这些配置参数提供了一种影响查询优化器所选查询计划的粗略方法。 如果优化器为某个特定查询选择的默认计划不是最优的, 一种临时解决方案是使用这些配置参数之一 强迫优化器选择一个不同的计划。 改进优化器所选计划质量的更好方法包括:调整计划器代价常数 (参见 Section 19.7.2)、 手动运行 ANALYZE、 增大 default_statistics_target 配置参数的值,以及使用 ALTER TABLE SET STATISTICS 增加针对特定列收集的统计量。

enable_async_append (boolean) #

启用或禁用查询计划器对异步感知附加计划类型的使用。 默认值为 on。

enable_bitmapscan (boolean) #

启用或禁用查询计划器对位图扫描计划类型的使用。 默认值为 on。

enable_distinct_reordering (boolean) #

启用或禁用查询计划器重新排列 DISTINCT 键以匹配输入路径的路径键的能力。默认值为 on。

enable_gathermerge (boolean) #

启用或禁用查询计划器对聚集合并计划类型的使用。 默认值为 on。

enable_group_by_reordering (boolean) #

控制查询计划器是否会产生一个让 GROUP BY 键按计划某个子节点(例如索引扫描)的键顺序排序的计划。 禁用时,查询计划器产生的计划只会把 GROUP BY 键排序以匹配 ORDER BY 子句(如果有的话)。 启用时,计划器会尝试产生一个更高效的计划。 默认值为 on。

enable_hashagg (boolean) #

启用或禁用查询计划器对哈希聚集计划类型的使用。 默认值为 on。

enable_hashjoin (boolean) #

启用或禁用查询计划器对哈希连接计划类型的使用。 默认值为 on。

enable_incremental_sort (boolean) #

启用或禁用查询计划器对 HTID 扫描计划类型的使用。 默认值为 on。

enable_indexscan (boolean) #

启用或禁用查询计划器对索引扫描和仅索引扫描计划类型的使用。 默认值为 on。 另请参见 enable_indexonlyscan。

enable_indexonlyscan (boolean) #

启用或禁用查询计划器对仅索引扫描计划类型的使用 (参见 Section 11.9)。 默认值为 on。 要让查询计划器考虑仅索引扫描, 还必须启用 enable_indexscan 设置。

enable_material (boolean) #

启用或禁用查询计划器对物化的使用。 完全抑制物化是不可能的,但关闭这个变量会阻止计划器插入 物化节点,除非出于正确性考虑必须这样做。 默认值为 on。

enable_memoize (boolean) #

启用或禁用查询计划器对 memoize 计划的使用,该计划用于在 嵌套循环连接中缓存参数化扫描的结果。 这种计划类型允许在当前参数的结果已经在缓存中时跳过对底层 计划的扫描。当新条目需要更多空间时,较少被查找的结果可能会 从缓存中被逐出。默认值为 on。

enable_mergejoin (boolean) #

启用或禁用查询计划器对合并连接计划类型的使用。 默认值为 on。

enable_nestloop (boolean) #

启用或禁用查询计划器对嵌套循环连接计划的使用。 完全抑制嵌套循环连接是不可能的,但关闭这个变量会在有其他 方法可用时阻止计划器使用它。默认值为 on。

enable_parallel_append (boolean) #

启用或禁用查询计划器对并行感知附加计划类型的使用。 默认值为 on。

enable_parallel_hash (boolean) #

启用或禁用查询计划器对带并行哈希的哈希连接计划类型的使用。 如果哈希连接计划未被启用,则没有效果。 默认值为 on。

enable_partition_pruning (boolean) #

启用或禁用查询计划器从查询计划中消除分区表分区的能力。 这也控制计划器生成允许查询执行器在查询执行期间移除(忽略) 分区的查询计划的能力。 默认值为 on。 详情请参见 Section 5.12.4。

enable_partitionwise_join (boolean) #

启用或禁用查询计划器对按分区连接的使用, 它允许分区表之间的连接通过连接匹配的分区来完成。 按分区连接目前只在连接条件包括全部分区键、且这些分区键具有 相同数据类型并有一对一匹配的子分区集时适用。 启用这个设置后,最终计划中内存使用受 work_mem 限制的节点数量可能会随着被扫描的 分区数量线性增长。这可能导致查询执行期间整体内存消耗大幅 增加。就内存和 CPU 而言,查询计划的开销也会显著变大。 默认值为 off。

enable_partitionwise_aggregate (boolean) #

启用或禁用查询计划器对按分区分组或聚集的使用, 它允许对分区表的分组或聚集针对每个分区单独执行。 如果 GROUP BY 子句没有包括分区键, 则只能按分区执行部分聚集,而最终聚集必须稍后执行。 启用这个设置后,最终计划中内存使用受 work_mem 限制的节点数量可能会随着被扫描的 分区数量线性增长。这可能导致查询执行期间整体内存消耗大幅 增加。就内存和 CPU 而言,查询计划的开销也会显著变大。 默认值为 off。

enable_presorted_aggregate (boolean) #

控制查询计划器是否会产生一个为查询的 ORDER BY / DISTINCT 聚集函数提供预排序行的计划。 禁用时,查询计划器产生的计划总是要求执行器在聚集每个包含 ORDER BY 或 DISTINCT 子句的聚集函数之前执行一次排序。 启用时,计划器会尝试产生一个更高效的计划,为聚集函数提供按 其聚集所需的顺序预排序的输入。 默认值为 on。

enable_self_join_elimination (boolean) #

启用或禁用查询计划器的一项优化,该优化分析查询树并把自连接 替换为语义等价的单次扫描。 只考虑普通表。 默认值为 on。

enable_seqscan (boolean) #

启用或禁用查询计划器对顺序扫描计划类型的使用。 完全抑制顺序扫描是不可能的,但关闭这个变量会在有其他方法 可用时阻止计划器使用它。默认值为 on。

enable_sort (boolean) #

启用或禁用查询计划器对显式排序步骤的使用。 完全抑制显式排序是不可能的,但关闭这个变量会在有其他方法 可用时阻止计划器使用它。默认值为 on。

enable_tidscan (boolean) #

启用或禁用查询计划器对 TID 扫描计划类型的使用。默认值为 on。

19.7.2. 优化器代价计算常数 #

本节描述的代价变量以任意的尺度度量。 只有它们的相对值才有意义,因此把它们全部按相同因子放大或缩小 不会改变计划器的选择。默认情况下,这些代价变量以顺序取页的代价 为基准;也就是说,惯例上把 seq_page_cost 设置为 1.0, 其他代价变量参照它设置。 但如果你愿意,也可以使用不同的尺度,例如某台特定机器上实际的 毫秒执行时间。

Note

遗憾的是,没有定义良好的方法来确定这些代价变量的理想取值。 最好把它们视为对特定安装将接收的整个查询组合的平均。 这意味着仅凭少量实验就更改它们是非常冒险的。

seq_page_cost (floating point) #

设置计划器对一系列顺序取页中一次磁盘页取回代价的估计。 默认值为 1.0。 对于特定表空间中的表和索引,可以通过设置同名的表空间参数来 覆盖这个值 (参见 ALTER TABLESPACE)。

random_page_cost (floating point) #

设置计划器对一次非顺序取回的磁盘页代价的估计。 默认值为 4.0。 对于特定表空间中的表和索引,可以通过设置同名的表空间参数来 覆盖这个值 (参见 ALTER TABLESPACE)。

相对于 seq_page_cost 减小这个值会让系统 更倾向于索引扫描;增大它则会让索引扫描显得相对更昂贵。 你可以把两个值一起调高或调低,以改变磁盘 I/O 代价相对于 CPU 代价(由以下参数描述)的重要性。

对持久存储的随机访问通常远比四倍的顺序访问昂贵。 不过,这里使用了一个较低的默认值(4.0), 因为对存储的大多数随机访问(例如索引读)被假定为发生在缓存 中。此外,网络附加存储的延迟往往会降低随机访问的相对开销。

如果你认为缓存命中的频率低于默认值所反映的水平, 并且网络延迟很小,可以增大 random_page_cost 以更好地反映随机存储读取的真实代价。 相对于顺序访问具有较高随机读代价的存储(例如磁盘), 或许也适合用更高的 random_page_cost 值来建模。 相应地,如果你的数据很可能完全在缓存中(例如数据库小于服务器 总内存),或者网络延迟很高, 那么减小 random_page_cost 可能是合适的。

Tip

虽然系统允许你把 random_page_cost 设置为低于 seq_page_cost, 但这样做在物理上不合理。不过,如果数据库完全缓存在 RAM 中,把两者设置为相等是有意义的,因为在这种情况下乱序访问 页面没有任何代价。另外,在重度缓存的数据库中, 你应当把这两个值都相对于 CPU 参数降低,因为取回一个已经在 RAM 中的页面的代价远小于正常情况。

cpu_tuple_cost (floating point) #

设置计划器对查询期间处理每行代价的估计。 默认值为 0.01。

cpu_index_tuple_cost (floating point) #

设置计划器对索引扫描期间处理每个索引条目代价的估计。 默认值为 0.005。

cpu_operator_cost (floating point) #

设置计划器对查询期间执行的每个操作符或函数代价的估计。 默认值为 0.0025。

parallel_setup_cost (floating point) #

设置计划器对启动并行工作进程代价的估计。 默认值为 1000。

parallel_tuple_cost (floating point) #

设置计划器把一个元组从一个并行工作进程传输到另一个进程的 代价估计。 默认值为 0.1。

min_parallel_table_scan_size (integer) #

设置要考虑并行扫描所必须扫描的表数据的最小数量。 对于并行顺序扫描,被扫描的表数据量总是等于表的大小, 但使用索引时被扫描的表数据量通常会少一些。 如果这个值没有指定单位,则以块为单位,即 BLCKSZ 字节,通常为 8kB。 默认值为 8 兆字节(8MB)。

min_parallel_index_scan_size (integer) #

设置要考虑并行扫描所必须扫描的索引数据的最小数量。 注意,并行索引扫描通常不会触及整个索引;有意义的是计划器认为 该扫描实际会触及的页面数量。 这个参数还用于决定某个特定的索引是否可以参与并行清理。 参见 VACUUM。 如果这个值没有指定单位,则以块为单位,即 BLCKSZ 字节,通常为 8kB。 默认值为 512 千字节(512kB)。

effective_cache_size (integer) #

设置计划器对单个查询可用的磁盘缓存有效尺寸的假设。 它会被计入使用索引的代价估计中;较高的值使索引扫描更可能被 使用,较低的值使顺序扫描更可能被使用。在设置这个参数时, 你应当同时考虑 PostgreSQL 的共享缓冲区,以及内核磁盘缓存中将被用于 PostgreSQL 数据文件的部分, 尽管有些数据可能同时存在于两处。此外,还要考虑不同表上预期的 并发查询数量,因为它们将不得不共享可用的空间。 这个参数对 PostgreSQL 分配的共享内存大小没有影响,也不会保留内核磁盘缓存; 它只用于估计目的。系统也不会假设数据在两次查询之间仍留在磁盘 缓存中。 如果这个值没有指定单位,则以块为单位,即 BLCKSZ 字节,通常为 8kB。 默认值为 4 吉字节(4GB)。 (如果 BLCKSZ 不是 8kB, 默认值会按比例缩放。)

jit_above_cost (floating point) #

设置激活 JIT 编译(如果已启用;参见 Chapter 30) 所需的查询代价。 执行 JIT 会消耗计划时间,但可以加速查询 执行。 把它设置为 -1 会禁用 JIT 编译。 默认值为 100000。

jit_inline_above_cost (floating point) #

设置 JIT 编译尝试内联函数和操作符所需的查询代价。 内联会增加计划时间,但可以提升执行速度。 把它设置为低于 jit_above_cost 的值没有意义。 把它设置为 -1 会禁用内联。 默认值为 500000。

jit_optimize_above_cost (floating point) #

设置 JIT 编译应用昂贵优化所需的查询代价。 这类优化会增加计划时间,但可以提升执行速度。 把它设置为低于 jit_above_cost 的值没有意义,而把它设置为高于 jit_inline_above_cost 的值也不太可能有好处。 把它设置为 -1 会禁用昂贵优化。 默认值为 500000。

19.7.3. 遗传算法优化器 #

遗传查询优化器(GEQO)是一种使用启发式搜索进行查询计划的 算法。它减少了复杂查询(连接许多关系的查询)的计划时间, 代价是有时产生的计划不如常规穷举搜索算法找到的计划。 更多信息请参见 Chapter 61。

geqo (boolean) #

启用或禁用遗传查询优化。 它默认开启。通常在生产环境中最好不要把它关闭; geqo_threshold 变量提供了对 GEQO 更细粒度的控制。

geqo_threshold (integer) #

当查询涉及的 FROM 项数量至少达到这个值时, 使用遗传查询优化来为它做计划。(注意,一个 FULL OUTER JOIN 构造只算作一个 FROM 项。)默认值为 12。对于较简单的查询, 通常最好使用常规的穷举搜索计划器;但对于涉及许多表的查询, 穷举搜索耗时过长,往往超过执行次优计划的代价。 因此,以查询规模作为阈值是管理 GEQO 使用的一种便利方式。

geqo_effort (integer) #

控制 GEQO 中计划时间与查询计划质量之间的权衡。这个变量必须是 1 到 10 范围内的整数。默认值为 5。较大的值会增加查询计划 所花的时间,但也会增加选出高效查询计划的可能性。

geqo_effort 实际上并不直接做任何事情;它只用于计算影响 GEQO 行为的其他变量(在下文描述)的默认值。 如果你愿意,也可以手工设置其他参数来取代它。

geqo_pool_size (integer) #

控制 GEQO 使用的池大小,即遗传种群中个体的数量。 它必须至少为 2,有用的值通常在 100 到 1000 之间。 如果它被设置为零(默认设置),则会基于 geqo_effort 和查询中的表数量选择一个合适的值。

geqo_generations (integer) #

控制 GEQO 使用的代数,即算法的迭代次数。 它必须至少为 1,有用的值与池大小处于同一范围。 如果它被设置为零(默认设置),则会基于 geqo_pool_size 选择一个合适的值。

geqo_selection_bias (floating point) #

控制 GEQO 使用的选择偏差。选择偏差是种群内的选择压力。 取值范围是 1.50 到 2.00;后者是默认值。

geqo_seed (floating point) #

控制 GEQO 用于在连接顺序搜索空间中选择随机路径的随机数 生成器的初始值。 该值的范围可以从零(默认值)到一。改变这个值会改变所探索的 连接路径集合,并可能让找到的最佳路径变得更好或更差。

19.7.4. 其他优化器选项 #

default_statistics_target (integer) #

为没有通过 ALTER TABLE SET STATISTICS 设置列特定目标的表列设置默认的 统计目标。较大的值会增加执行 ANALYZE 所需的时间,但可能改善计划器估计的质量。 默认值为 100。有关 PostgreSQL 查询计划器如何使用统计信息的更多信息,请参见 Section 14.2。

constraint_exclusion (enum) #

控制查询计划器使用表约束来优化查询。 constraint_exclusion 的允许值是 on(检查所有表的约束)、 off(从不检查约束)和 partition(只检查继承子表和 UNION ALL 子查询的约束)。 partition 是默认设置。 它常与传统继承树一起使用以提升性能。

当这个参数允许对某个特定的表这样做时,计划器会把查询条件与 该表的 CHECK 约束进行比较, 并跳过那些条件与约束相矛盾的表。 例如:

CREATE TABLE parent(key integer, ...);
CREATE TABLE child1000(check (key between 1000 and 1999)) INHERITS(parent);
CREATE TABLE child2000(check (key between 2000 and 2999)) INHERITS(parent);
...
SELECT * FROM parent WHERE key = 2400;

启用约束排除后,这条 SELECT 将完全不会扫描 child1000,从而提升 性能。

目前,约束排除默认只对那些常用于通过继承树实现表分区的情形 启用。对所有表开启它会带来额外的计划开销,这种开销在简单查询 上相当明显,而且大多数时候对简单查询没有好处。 如果你没有使用传统继承进行分区的表,你可能更愿意把它完全 关闭。(注意,分区表的等价功能由一个单独的参数控制, 即 enable_partition_pruning。)

有关使用约束排除实现分区的更多信息, 请参见 Section 5.12.5。

cursor_tuple_fraction (floating point) #

设置计划器对一个游标的行将被取回比例的估计。 默认值为 0.1。这个设置的较小值会让计划器偏向为游标使用 “快速启动”计划,这类计划会很快取回最初的几行, 但取回所有行可能花费很长时间。较大的值则更强调总的估计时间。 在最大设置 1.0 下,游标的计划方式与常规查询完全相同, 只考虑总的估计时间而不考虑最初几行多快能被交付。

from_collapse_limit (integer) #

如果结果得到的 FROM 列表不超过这么多项,计划器会把子查询合并进上层查询。 较小的值会减少计划时间,但可能产生较差的查询计划。 默认值为 8。 更多信息请参见 Section 14.3。

把这个值设置为 geqo_threshold 或更大可能触发 GEQO 计划器的使用,导致非最优的计划。 参见 Section 19.7.3。

jit (boolean) #

决定 PostgreSQL 是否可以使用 JIT 编译(如果可用; 参见 Chapter 30)。 默认值为 on。

join_collapse_limit (integer) #

只要结果得到的列表不超过这么多项, 计划器就会把显式 JOIN 构造(FULL JOIN 除外)改写为 FROM 项的列表。 较小的值会减少计划时间,但可能产生较差的查询计划。

默认情况下,这个变量被设置为与 from_collapse_limit 相同, 这对大多数用途是合适的。把它设置为 1 可以阻止任何对显式 JOIN 的重排。 这样,查询中指定的显式连接顺序就是关系实际被连接的顺序。 由于查询计划器并不总是选择最优的连接顺序, 高级用户可以选择临时把这个变量设置为 1, 然后显式指定他们想要的连接顺序。 更多信息请参见 Section 14.3。

把这个值设置为 geqo_threshold 或更大可能触发 GEQO 计划器的使用,导致非最优的计划。 参见 Section 19.7.3。

plan_cache_mode (enum) #

已准备语句(无论是显式准备的,还是例如由 PL/pgSQL 隐式生成的)可以使用自定义计划或通用计划来执行。 自定义计划在每次执行时使用该次特定的参数值集合重新制定, 而通用计划不依赖参数值,可以跨执行复用。 因此,使用通用计划可以节省计划时间,但如果理想计划强烈依赖 参数值,那么通用计划可能是低效的。 这两个选项之间的选择通常自动做出,但可以用 plan_cache_mode 覆盖。 允许的值是 auto(默认值)、 force_custom_plan 和 force_generic_plan。 这个设置在执行缓存计划时被考虑,而不是在准备它时。 更多信息请参见 PREPARE。

recursive_worktable_factor (floating point) #

设置计划器对 递归 查询工作表平均尺寸的估计,表示为该查询初始非递归项 估计尺寸的倍数。这有助于计划器为工作表与查询的其他表的连接 选择最合适的方法。 默认值为 10.0。当递归从一步到下一步的 “扇出”较低时(例如最短路径查询), 像 1.0 这样的较小值可能有帮助。 图分析类查询可能受益于大于默认值的设置。