↑↓ 选择 ↵ 打开 ⌫ 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

百科 / 执行计划节点 / 控制

Limit

Limit

将执行计划的行数限制和偏移量应用于子计划输出。

当前查看 PostgreSQL 18.6。

说明

将执行计划的行数限制和偏移量应用于子计划输出。

核心节点标签
T_Limit
结构化 EXPLAIN 节点类型
Limit
输入
一个子计划
输出
选定范围的元组
执行器初始化函数
ExecInitLimit
内存机制
unclassified

EXPLAIN 名称与属性

结构化格式使用上述 Node Type。文本格式名称还可能包含操作、策略、连接类型、扫描方向或聚合阶段属性。

此源码记录的文本名称:Limit.

并行感知与并行安全是不同的计划属性。在并行工作进程内运行的节点不一定是并行感知节点。

内存与临时存储

本次抽取不为此节点设定统一的内存上限或落盘策略。请查看同一构建的实现、相关表达式或提供方。

并行执行与运行信息采集

以下源码回调可以协调执行或收集工作进程的测量数据。回调存在不代表该节点普遍支持共享并行扫描或共享状态。

此构建的回调:none extracted from this node implementation.

同版本手册说明

估计总代价:假定计划节点完整执行,即取出所有可用行时的代价。实际执行时,父节点可能尚未读取全部可用行就提前停止(见下方 LIMIT 示例)。

与普通排序相比,增量排序可在整个结果集尚未排完时就返回元组,尤其有利于优化带 LIMIT 的查询。它还可能减少内存用量和排序溢写磁盘的概率,但代价是将结果集拆成多个排序批次所带来的额外开销。

查询与上例相同,只是增加 LIMIT,不再需要取回全部行,因此规划器改变了选择。Index Scan 节点的总成本和行数仍按完整执行显示,但 Limit 预计只取回五分之一的行就停止,其总成本也只有五分之一,这才是查询的实际估计成本。与在此前计划上添加 Limit 相比,此计划更优,因为 Limit 无法避免位图扫描的启动成本,原方案的总成本仍会超过 25 个单位。

实际值与估计值有时并不吻合,但并不表示有问题。例如 LIMIT 或类似作用提前停止计划节点执行时就会如此。以前面的 LIMIT 查询为例:

Index Scan 节点的估计成本和行数按完整执行显示。但实际执行中,Limit 在取得两行后就不再请求,因此实际行数仅为 2,运行时间也低于成本估计所暗示的值。这不是估计错误,只是估计值与实际值的展示口径不同。

归并连接的测量结果也可能产生误导。若一侧输入已耗尽,另一侧的下一个键值又大于已耗尽输入的最后一个键值,就不会再有匹配,因此会停止读取另一侧。这样便未读取该子节点的全部行,类似 LIMIT 的情况。另外,外侧(第一个)子节点有重复键值时,内侧(第二个)子节点会回退并重新扫描匹配该键值的行。EXPLAIN ANALYZE 会将内侧重复输出的行计作额外的真实行。因此外侧重复值很多时,内侧计划节点报告的实际行数可能显著超过内侧关系中的实际行数。

本版手册中的示例

示例摘自 PostgreSQL 18.6 手册;本百科未实际执行此示例。

如果计划中的某一部分已经保证了所需排序键前缀的顺序,规划器也可能改用 Incremental Sort 步骤:

EXPLAIN SELECT * FROM tenk1 ORDER BY hundred, ten LIMIT 100;

                                              QUERY PLAN
------------------------------------------------------------------------------------------------
 Limit  (cost=19.35..39.49 rows=100 width=244)
   ->  Incremental Sort  (cost=19.35..2033.39 rows=10000 width=244)
         Sort Key: hundred, ten
         Presorted Key: hundred
         ->  Index Scan using tenk1_hundred on tenk1  (cost=0.29..1574.20 rows=10000 width=244)

示例摘自 PostgreSQL 18.6 手册;本百科未实际执行此示例。

下面的示例展示 LIMIT 的作用:

EXPLAIN SELECT * FROM tenk1 WHERE unique1 < 100 AND unique2 > 9000 LIMIT 2;

                                     QUERY PLAN
-------------------------------------------------------------------------------------
 Limit  (cost=0.29..14.28 rows=2 width=244)
   ->  Index Scan using tenk1_unique2 on tenk1  (cost=0.29..70.27 rows=10 width=244)
         Index Cond: (unique2 > 9000)
         Filter: (unique1 < 100)

执行器实现说明

nodeLimit.c:在适当情况下限制查询结果的例程。

这是一个非常简单的节点,仅对某个子计划返回的元组流执行 LIMIT/OFFSET 筛选。

首次调用此节点,因此计算 limit/offset。(不能更早计算,因为 ExecInitLimit 阶段尚未设置上层节点传来的参数。)这还会设置 position = 0,并将状态改为 LIMIT_RESCAN。

子计划返回的元组太少,无法产生任何输出。

需要保存边界处的元组,以在后续执行中比较并识别并列值。

核心源码中的 EXPLAIN 标识

case T_Limit:
			pname = sname = "Limit";
			break;

本构建中的 EXPLAIN 标签

文本格式标签结构化节点标识
LimitLimit

相关条目

文档与源码

来源构建
版本
18.6
构建
PostgreSQL 18.6 source archive
来源指纹
555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f

版本比较

PostgreSQL 17 → 18: 无变化。

比较已记录的接口与属性,排除来源指纹和构建元数据。某个样本中没有记录,不能据此判断实际引入或移除的版本。

相关条目

导出 JSON · 返回执行计划节点 · 收录范围为 PostgreSQL 10 至 20;最早采样版本不一定是实际引入版本。