Redrock Postgres 搜索 英文
版本: 9.3 / 9.4 / 9.5 / 9.6 / 10 / 11 / 12 / 13 / 14 / 15 / 16 / 17

19.7. 查询规划 #

19.7.1. 规划器方法配置
19.7.2. 规划器成本常量
19.7.3. 遗传查询优化器
19.7.4. 其他规划器选项

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 (布尔) #

启用或禁用查询计划程序使用哈希联接计划类型。默认值为 on

enable_incremental_sort (布尔) #

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

enable_indexscan (布尔) #

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

enable_indexonlyscan (布尔) #

启用或禁用查询计划程序使用仅索引扫描计划类型(请参阅 第 11.9 节)。默认值为 on。还必须启用 enable_indexscan 设置,以便查询计划程序考虑仅索引扫描。

enable_material (布尔) #

启用或禁用查询计划程序使用物化。不可能完全禁止物化,但关闭此变量可以阻止计划程序插入物化节点,除非在正确的情况下需要。默认值为 on

enable_memoize (布尔) #

启用或禁用查询计划程序使用备忘计划来缓存嵌套循环联结中参数化扫描结果。此计划类型允许当当前参数结果已在缓存中时,跳过对底层计划的扫描。当需要更多空间来容纳新条目时,可能会从缓存中删除较不常用的查询结果。默认值为 on

enable_mergejoin (布尔) #

启用或禁用查询规划程序使用并行连接计划类型。默认值为 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. Planner 计算常量 #

本节所述cost(成本) 变量在任意标尺中进行度量。只有它们的相对值才有意义,因此统一向上或向下扩展它们不会对 planner 的选择产生任何变化。默认情况下,这些 cost 变量基于页面顺序获取的成本;即,seq_page_cost 通常设置为 1.0,其他 cost 变量则参照此成本进行设置。但是,如果愿意,您可以使用不同的标尺,如特定机器上以毫秒为单位的实际执行时间。

注意

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

seq_page_cost (浮点数) #

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

random_page_cost (浮点数) #

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

相对于 seq_page_cost 降低这个值将导致系统倾向于索引扫描;提高该值会使索引扫描看上去相对更昂贵。您可以同时提高或降低这两个值,以更改磁盘 I/O 成本相对于以下参数所述的 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 (integer) #

设置必须扫描的索引数据的最小量,以便将并行扫描视为已考虑的扫描。请注意,并行索引扫描通常不会影响整个索引;相关索引是规划器认为实际会受到扫描影响的页面数。此参数还用于决定某个特定索引是否可以参与并行清理。请参阅 VACUUM。如果不带单位指定此值,则将其视为块,即 BLCKSZ 字节,通常为 8kB。默认值为 512 千字节 (512kB)。

effective_cache_size (integer) #

设置规划器关于可供单个查询使用的磁盘缓存有效容量的假设。此假设纳入了使用索引成本的估计中;较高的值使其更有可能使用索引扫描,而较低的值使其更有可能使用顺序扫描。在设置此参数时,您应同时考虑 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 (integer) #

控制 GEQO 中规划时间与查询计划质量之间的平衡。此变量必须是 1 到 10 之间的整数。默认值为 5。较大的值会增加用于进行查询规划的时间,但也增加了选择高效查询计划的可能性。

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

geqo_pool_size (integer) #

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

geqo_generations (integer) #

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

geqo_selection_bias (floating point) #

控制 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 (布尔值) #

确定是否JITPostgreSQL 如果可用,可以使用编译(请参见 第 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,可能在递归从一个步骤到另一个步骤具有较低的扇出时会很有帮助,例如最短路径查询中。图表分析查询可能受益于大于默认值的值。