18.6. 查询规划

18.6.1. 规划器方法配置

这些配置参数提供了影响查询优化器选择查询规划的原始方法。如果优化器 为特定的查询选择的缺省规划并不是最优,那么我们就可以通过使用这些 配置参数强制优化器选择一个更好的规划来temporary解决这个 问题。不过,永久地关闭这些设置几乎从不是个好主意。更好的改善优化器 选择规划的方法包括调节Section 18.6.2、 更频繁运行ANALYZE、增大配置参数 default_statistics_target的值、使用 ALTER TABLE SET STATISTICS为某个字段增加收集的 统计信息。

enable_bitmapscan(boolean)

打开或者关闭规划器对位图扫描规划类型的使用。缺省是on

enable_hashagg(boolean)

打开或者关闭规划器对Hash聚集规划类型的使用。缺省是on

enable_hashjoin(boolean)

打开或者关闭规划器对Hash连接规划类型的使用。缺省是on

enable_indexscan(boolean)

打开或者关闭规划器对索引扫描规划类型的使用。缺省是on

enable_material(boolean)

启用或禁用查询规划器的具体化的使用。它可以完全废止具体化, 但禁用该变量后悔阻止规划器插入具体节点,除非是要求得正确得当。 缺省是on

enable_mergejoin(boolean)

打开或者关闭规划器对融合连接规划类型的使用。缺省是 on

enable_nestloop(boolean)

打开或者关闭规划器对嵌套循环连接规划类型的使用。我们不可能完全 消除嵌套循环连接,但是把这个变量关闭就会让规划器在存在其它方法的 时候优先选择其它方法。缺省是on.

enable_seqscan(boolean)

打开或者关闭规划器对顺序扫描规划类型的使用。我们不可能完全消除 顺序扫描,但是把这个变量关闭会让规划器在存在其它方法的时候优先 选择其它方法。缺省是on.

enable_sort(boolean)

打开或者关闭规划器使用明确的排序步骤。我们不可能完全消除明确的排序, 但是把这个变量关闭可以让规划器在存在其它方法的时候优先选择其它方法。 缺省是on

enable_tidscan(boolean)

打开或者关闭规划器对 TID 扫描规划类型的使用。缺省是on.

18.6.2. 规划器开销常量

本节中描述的cost可以按照任意标准度量。我们只关心其相对值, 因此以相同的系数缩放它们将不会对规划器产生任何影响。默认情况下,它们 以抓取顺序页的开销作为基准单位。也就是说将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的开销(在下面的参数 中描述)。

Tip: 虽然允许你将random_page_cost设置的比 seq_page_cost小,但是物理上的实际情况并不受此影响。 然而当所有数据库都位于内存中时,两者设置为相等是非常合理的,因为 在此情况下,乱序抓取并不比顺序抓取开销更大。同样,在缓冲率很高的 数据库上,你应当相对于 CPU 开销同时降低这两个值,因为获取内存中 的页比通常情况下的开销小许多。

cpu_tuple_cost(floating point)

设置规划器计算在一次查询中处理一个数据行的开销。缺省是 0.01 。

cpu_index_tuple_cost(floating point)

设置规划器计算在一次索引扫描中处理每条索引行的开销。缺省是 0.005 。

cpu_operator_cost(floating point)

设置规划器计算在一次查询中执行一个操作符或函数的开销。缺省是 0.0025 。

effective_cache_size(integer)

为规划器设置在一次索引扫描中可用的磁盘缓冲区的有效大小。 这个参数会在计算一个索引的预计开销值的时候加以考虑。更高的数值 会导致更可能使用索引扫描,更低的数值会导致更有可能选择顺序扫描。 在设置这个参数的时候,你还应该考虑PostgreSQL 的数据文件会使用的共享缓冲区和内核的磁盘缓冲区。另外,还要考虑 预计会使用不同索引的并发查询数目,因为它们必须共享可用的内存空间。 这个参数对PostgreSQL分配的共享内存 大小没有影响,它也不会使用内核磁盘缓冲,它只用于估算。数值是用 磁盘页来计算的,通常每个页面是 8192 字节。缺省是 16384 (128MB)。

18.6.3. 基因查询优化器

GEQO是一个使用探索式搜索来执行查询规划的算法。它可以降低负载查询的规划时间。 同时,GEQO的检索是随机的,因此它的规划可能会不可确定。 更多信息参阅Chapter 50

geqo(boolean)

允许或禁止基因查询优化,通常情况下最好不要把它应用于生产, 缺省是允许。geqo_threshold 变量提供了一种为特定类别的 查询关闭 GEQO 的更精细方法。

geqo_threshold(integer)

只有当涉及的FROM关系数量至少有这么多个的时候, 才使用基因查询优化。对于数量小于此值的查询,也许使用判定性的 穷举搜索更有效。但是对于有许多表的查询,规划器做判断要花很多时间。 缺省是12。请注意一个FULL OUTER JOIN构造只算一个 FROM项。

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.5到2.0之间;缺省是2.0。

geqo_seed(floating point)

控制GEQO使用的随机数产生器的初始值,用以选择随机路径。 这个值可以从0(缺省)到1。修改这个值会改变连接路径搜索的设置, 同时会找到最优或最差路径。

18.6.4. Other Planner Options

default_statistics_target(integer)

为没有用ALTER TABLE SET STATISTICS设置字段相关目标的 表中其它字段设置缺省统计目标。更大的数值增加了ANALYZE 所需要的时间,但是可能会改善规划器的估计质量。缺省值是 100 。 有关PostgreSQL的查询规划器使用的统计的更多信息, 请参考节Section 14.2

constraint_exclusion(enum)

控制使用表约束的查询规划的优化查询。 The allowed values ofconstraint_exclusionare on(examine constraints for all tables), off(never examine constraints), and partition(examine constraints only for inheritance child tables andUNION ALLsubqueries). partitionis the default setting. It is often used with inheritance and partitioned tables to improve performance.

如果这个参数支持一个特定的表 ,那么规划器用查询条件和 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。这样可以在使用继承制作分区表的时候提高性能。

目前,约束排除在缺省启用,只用于经常进行表分区的情况。 为所有表启用约束排除会明显增加规划开销,特别是在一个简单查询时, 对简单查询而言,频繁的约束排除不会产生任何好处。 如果没有分区表时,最好是完全关闭该选项。

参阅Section 5.9.4以获得更多信息。

cursor_tuple_fraction(floating point)

设置游标将被检索的行的分数的规划估计。缺省是0.1。小于该值时会为游标偏向使用 "fast start"规划,这将快速检索前几行,虽然可能花费很长的时间读取所有行。 大于该值时会更重视总体的估计时间。最大可设置为1.0,此时游标会被规划为类似于定期查询, 只考虑总估算时间,而不考虑多久才会输出第一个行。

from_collapse_limit(integer)

如果生成的FROM列表不超过这个限制的项数, 规划器将把子查询融合到上层查询。小的数值降低规划的时间,但是可能 会生成差些的查询计划。缺省是 8 。更多信息请查看节13.3。

将这个值设置为geqo_threshold或更大,可能触发 使用GEQO规划器,从而产生不确定的计划。 参阅Section 18.6.3

join_collapse_limit(integer)

如果得出的列表不超过这个数目的项,那么规划器将把除 FULL JOIN之外的JOIN构造抹平到 FROM列表项中。小的数值降低规划的时间,但是可能会生成 差些的查询计划。

缺省时,这个值和from_collapse_limit相同, 这样适合大多数场合。把它设置为 1 则避免任何JOIN 的融合,这样就将明确使用语句中的连接顺序。查询优化器并不是总能 选取最优的连接顺序;高级用户可以选择暂时把这个变量设置为 1 , 然后明确地声明他们需要的连接顺序。 更多信息参见节Section 14.3

将这个值设置为geqo_threshold或更大,可能触发 使用GEQO规划器,从而产生不确定的计划。参阅Section 18.6.3