2024年9月26日: PostgreSQL 17 发布!
支持版本:当前 (17) / 16 / 15 / 14 / 13 / 12
开发版本:devel
不支持的版本:11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1

19.7. 查询规划 #

19.7.1. 规划器方法配置 #

这些配置参数提供了一种粗略的方法来影响查询优化器选择的查询计划。如果优化器为特定查询选择的默认计划不是最佳的,那么一个临时的解决方案是使用这些配置参数之一来强制优化器选择不同的计划。改进优化器选择的计划质量的更好方法包括调整规划器成本常量(参见 第 19.7.2 节)、手动运行 ANALYZE、增加 default_statistics_target 配置参数的值,以及使用 ALTER TABLE SET STATISTICS 增加为特定列收集的统计信息的数量。

enable_async_append (boolean) #

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

enable_bitmapscan (boolean) #

启用或禁用查询规划器使用位图扫描计划类型。默认值为 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) #

启用或禁用查询规划器使用增量排序步骤。默认值为 on

enable_indexscan (boolean) #

启用或禁用查询规划器使用索引扫描计划类型。默认值为 on

enable_indexonlyscan (boolean) #

启用或禁用查询规划器使用仅索引扫描计划类型(参见 第 11.9 节)。默认值为 on

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。有关详细信息,请参见 第 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 BYDISTINCT 子句的聚合函数进行聚合之前执行排序的计划。启用后,计划器将尝试生成一个更有效的计划,该计划为聚合函数提供按其聚合所需的顺序预排序的输入。默认值为 on

enable_seqscan (boolean) #

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

enable_sort (boolean) #

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

enable_tidscan (boolean) #

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

19.7.2. 规划器成本常量 #

本节中描述的 成本 变量以任意量表度量。只有它们的相对值才有意义,因此将它们全部向上或向下缩放相同的因子不会改变规划器的选择。默认情况下,这些成本变量基于顺序页面获取的成本;也就是说,seq_page_cost 通常设置为 1.0,其他成本变量则参照此值设置。但是,如果您愿意,可以使用不同的量表,例如特定机器上的实际执行时间(以毫秒为单位)。

注意

不幸的是,没有一种定义明确的方法来确定成本变量的理想值。它们最好被视为特定安装将接收到的所有查询组合的平均值。这意味着仅仅根据几个实验来更改它们是非常危险的。

seq_page_cost (浮点数) #

设置规划器对属于一系列顺序获取的磁盘页面获取成本的估计。默认值为 1.0。可以通过设置相同名称的表空间参数来覆盖特定表空间中表和索引的此值(请参阅 ALTER TABLESPACE)。

random_page_cost (浮点数) #

设置规划器对非顺序获取的磁盘页面的成本估计。默认值为 4.0。可以通过设置相同名称的表空间参数来覆盖特定表空间中表和索引的此值(请参阅 ALTER TABLESPACE)。

相对于 seq_page_cost 降低此值将导致系统更倾向于使用索引扫描;提高它将使索引扫描看起来相对更昂贵。您可以一起提高或降低这两个值来改变磁盘 I/O 成本相对于 CPU 成本的重要性,CPU 成本由以下参数描述。

机械磁盘存储的随机访问通常比顺序访问贵得多。但是,使用较低的默认值(4.0),因为大多数对磁盘的随机访问(例如索引读取)被认为是在缓存中。默认值可以被认为是将随机访问建模为比顺序访问慢 40 倍,同时预计 90% 的随机读取将被缓存。

如果您认为 90% 的缓存率对于您的工作负载是一个错误的假设,您可以增加 random_page_cost 以更好地反映随机存储读取的真实成本。相应地,如果您的数据很可能完全位于缓存中,例如当数据库小于服务器的总内存时,降低 random_page_cost 可能是合适的。存储相对于顺序访问具有较低的随机读取成本(例如固态驱动器)也可以通过更低的 random_page_cost 值(例如 1.1)更好地建模。

提示

尽管系统允许您将 random_page_cost 设置为小于 seq_page_cost,但这在物理上是不合理的。但是,如果数据库完全缓存在 RAM 中,将它们设置为相等是有意义的,因为在这种情况下,按顺序访问页面没有任何损失。此外,在高度缓存的数据库中,您应该相对于 CPU 参数降低这两个值,因为获取已经在 RAM 中的页面的成本远小于通常情况下的成本。

cpu_tuple_cost (浮点数) #

设置规划器对查询期间处理每一行的成本的估计。默认值为 0.01。

cpu_index_tuple_cost (浮点数) #

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

cpu_operator_cost (浮点数) #

设置规划器对查询期间执行的每个运算符或函数的处理成本的估计。默认值为 0.0025。

parallel_setup_cost (浮点数) #

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

parallel_tuple_cost (浮点数) #

设置规划器对将一个元组从并行工作进程传输到另一个进程的成本的估计。默认值为 0.1。

min_parallel_table_scan_size (整数) #

设置必须扫描的最小表数据量,以便考虑并行扫描。对于并行顺序扫描,扫描的表数据量始终等于表的尺寸,但是当使用索引时,扫描的表数据量通常会更少。如果此值在没有单位的情况下指定,则将其视为块,即 BLCKSZ 字节,通常为 8kB。默认值为 8 兆字节 (8MB)。

min_parallel_index_scan_size (整数) #

设置必须扫描的最小索引数据量,以便考虑并行扫描。请注意,并行索引扫描通常不会触及整个索引;相关的是规划器认为实际上会被扫描触及的页面数量。此参数也用于决定特定索引是否可以参与并行 vacuum。请参阅 VACUUM。如果此值在没有单位的情况下指定,则将其视为块,即 BLCKSZ 字节,通常为 8kB。默认值为 512 千字节 (512kB)。

effective_cache_size (整数) #

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

jit_above_cost (浮点数) #

设置查询成本,高于该成本将激活 JIT 编译(如果已启用(请参阅 第 30 章)。执行JIT会增加计划时间,但可以加快查询执行速度。将此设置为 -1 会禁用 JIT 编译。默认值为 100000

jit_inline_above_cost (浮点数) #

设置查询成本,高于该成本 JIT 编译将尝试内联函数和运算符。内联会增加计划时间,但可以提高执行速度。将此设置为小于 jit_above_cost 没有意义。将此设置为 -1 会禁用内联。默认值为 500000

jit_optimize_above_cost (浮点数) #

设置 JIT 编译应用昂贵优化的查询成本上限。此类优化会增加规划时间,但可以提高执行速度。将此值设置为小于 jit_above_cost 没有意义,并且将其设置为大于 jit_inline_above_cost 也不太可能带来益处。将其设置为 -1 将禁用昂贵优化。默认值为 500000

19.7.3. 遗传查询优化器 #

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

geqo (布尔值) #

启用或禁用遗传查询优化。默认情况下处于启用状态。在生产环境中通常最好不要将其关闭;geqo_threshold 变量提供对 GEQO 的更细粒度控制。

geqo_threshold (整数) #

使用遗传查询优化来规划至少包含此数量的 FROM 项的查询。(请注意,FULL OUTER JOIN 结构仅计为一个 FROM 项。)默认值为 12。对于更简单的查询,通常最好使用常规的穷举搜索规划器,但对于包含许多表的查询,穷举搜索需要很长时间,通常比执行次优计划的惩罚时间更长。因此,对查询大小的阈值是管理 GEQO 使用的便捷方式。

geqo_effort (整数) #

控制 GEQO 中规划时间和查询计划质量之间的权衡。此变量必须是 1 到 10 之间的整数。默认值为 5。更大的值会增加执行查询规划所花费的时间,但也增加了选择高效查询计划的可能性。

geqo_effort 实际上并没有直接执行任何操作;它仅用于计算影响 GEQO 行为的其他变量的默认值(如下所述)。如果您愿意,可以手动设置其他参数。

geqo_pool_size (整数) #

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

geqo_generations (整数) #

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

geqo_selection_bias (浮点数) #

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

geqo_seed (浮点数) #

控制 GEQO 使用的随机数生成器的初始值,用于选择连接顺序搜索空间中的随机路径。该值可以从 0(默认值)到 1。改变该值会改变探索的连接路径集,并可能导致找到更好的或更差的最佳路径。

19.7.4. 其他规划器选项 #

default_statistics_target (整数) #

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

constraint_exclusion (枚举) #

控制查询规划器使用表约束优化查询的方式。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。)

有关使用约束排除实现分区的更多信息,请参阅 第 5.12.5 节

cursor_tuple_fraction (浮点数) #

设置规划器对游标将检索的行数的比例的估计。默认值为 0.1。较小的设置值会使规划器倾向于对游标使用 快速启动 计划,这将快速检索前几行,但可能需要很长时间才能获取所有行。较大的值会更多地强调估计的总时间。在 1.0 的最大设置下,游标的规划方式与常规查询完全相同,仅考虑估计的总时间,而不考虑第一行可能何时交付。

from_collapse_limit (整数) #

如果生成的 FROM 列表将不超过此数量的项,规划器会将子查询合并到上级查询中。较小的值会减少规划时间,但可能会生成较差的查询计划。默认值为 8。有关更多信息,请参见 第 14.3 节

将此值设置为 geqo_threshold 或更大可能会触发 GEQO 规划器的使用,从而导致非最佳计划。请参见 第 19.7.3 节

jit (布尔值) #

确定是否JIT编译可以由 PostgreSQL 使用,如果可用(请参见 第 30 章)。默认值为 on

join_collapse_limit (整数) #

规划器会将显式 JOIN 结构(除了 FULL JOIN)重写为 FROM 项列表,只要不会导致不超过此数量的项的列表即可。较小的值会减少规划时间,但可能会生成较差的查询计划。

默认情况下,此变量设置为与 from_collapse_limit 相同,这适用于大多数用途。将其设置为 1 会阻止对显式 JOIN 进行任何重新排序。因此,查询中指定的显式连接顺序将是实际连接关系的顺序。由于查询规划器并不总是选择最佳连接顺序,因此高级用户可以选择暂时将此变量设置为 1,然后显式指定他们想要的连接顺序。有关更多信息,请参见 第 14.3 节

将此值设置为 geqo_threshold 或更大可能会触发 GEQO 规划器的使用,从而导致非最佳计划。请参见 第 19.7.3 节

plan_cache_mode (枚举) #

可以使用自定义计划或通用计划执行已准备好的语句(显式准备或隐式生成,例如通过 PL/pgSQL)。自定义计划是为每次执行使用其特定的参数值集而重新创建的,而通用计划不依赖于参数值,并且可以在跨执行之间重复使用。因此,使用通用计划可以节省规划时间,但如果理想计划在很大程度上取决于参数值,那么通用计划可能会效率低下。通常会自动进行这两种选项之间的选择,但可以使用 plan_cache_mode 覆盖它。允许的值为 auto(默认值)、force_custom_planforce_generic_plan。此设置在执行缓存计划时会考虑,而不是在准备缓存计划时考虑。有关更多信息,请参见 PREPARE

recursive_worktable_factor (浮点数) #

设置规划器对 递归查询 的工作表的平均大小的估计,以查询的初始非递归项的估计大小的倍数表示。这有助于规划器选择最适合将工作表与查询的其他表连接的方法。默认值为 10.0。较小的值(例如 1.0)在递归从一步到下一步的 扩展 很低时可能会有所帮助,例如在最短路径查询中。图分析查询可能受益于大于默认值的设置。

提交更正

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