{"Entry":{"collection":"plan","key":"limit","name":"Limit","aliases":["Limit","T_Limit"],"metadata":{"aliases":["Limit","T_Limit"],"category":"Control","content_hash":"a296f240365dc41f7785fa0d6c4712a73c40fb146aa2bd40ef4796fb96cf9b5b","derived_content_hash":"cf446567809dad8b5a39f18a76c4c965e9cb476ae2acaa5973f14e0259b9ab76","imported_at":"2026-09-30T00:40:44.077866+08:00","name":"Limit","name_zh":"Limit","slug":"limit","summary":"Applies the plan row-count and offset bounds to its child output."}},"Definition":{"Collection":"plan","Key":"limit","SourceDatabase":"center","Version":"18","SourceTable":"plan_node","SourceKey":"limit","SourceRevision":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","Facts":{"comparison_data":{"initializer":"ExecInitLimit","memory_mechanism":"unclassified","node_tag":"T_Limit","parallel_callbacks":[],"partial_modes":[],"strategies":[],"text_names":["Limit"]},"comparison_hash":"b3c3324250451387ccc954865a29ed33ce3a9dd7167e0e44ed92802679df763a","description":["Applies the plan row-count and offset bounds to its child output."],"description_zh":"对子计划输出应用行数和偏移边界。","description_zh_html":"\u003cp\u003e对子计划输出应用行数和偏移边界。\u003c/p\u003e\u003cp\u003e核心节点标识：\u003ccode\u003eT_Limit\u003c/code\u003e；EXPLAIN 名称：\u003ccode\u003eLimit\u003c/code\u003e。\u003c/p\u003e\u003cp\u003e本版本源码中的并行执行或观测回调：该节点实现中未提取到此类回调。回调的存在不表示该节点必然支持共享并行扫描；在并行工作进程中执行也不等于具有并行感知能力。\u003c/p\u003e\u003ch3\u003e同版本中文手册节选\u003c/h3\u003e\u003cp\u003e\n    查询计划的结构是一棵由\u003cem class=\"firstterm\"\u003e计划节点\u003c/em\u003e组成的树。树的最底层是扫描节点，它们从表中返回原始行。不同的表访问方法对应不同类型的扫描节点，例如顺序扫描、索引扫描和位图索引扫描。也有一些并非表的行来源，例如 \u003ccode class=\"literal\"\u003eVALUES\u003c/code\u003e 子句和 \u003ccode class=\"literal\"\u003eFROM\u003c/code\u003e 中的返回集合函数，它们也各自有对应的扫描节点类型。如果查询需要对原始行执行连接、聚合、排序或其他操作，那么扫描节点之上还会出现额外的节点来完成这些操作。同样，这些操作通常不止一种实现方式，因此这里也会出现不同的节点类型。\u003ccode class=\"command\"\u003eEXPLAIN\u003c/code\u003e 会为计划树中的每个节点输出一行，显示基本节点类型以及规划器对该计划节点执行代价的估计值。还可能出现相对节点摘要行缩进的附加行，用来显示该节点的更多属性。第一行，也就是最顶层节点的摘要行，给出了整个计划的估计总执行代价；规划器力图最小化的正是这个数字。\n   \u003c/p\u003e\u003cp\u003e\n    下面是一个简单的示例，仅用于展示输出的样子：\n\n\u003c/p\u003e\u003cp\u003e\n    由于这个查询没有 \u003ccode class=\"literal\"\u003eWHERE\u003c/code\u003e 子句，它必须扫描表中的所有行，因此规划器选择了一个简单的顺序扫描计划。圆括号中的数字从左到右依次表示：\n\n    \u003c/p\u003e\u003cp\u003e\n    这些代价使用由规划器代价参数决定的任意单位来衡量（见\u003ca class=\"xref\" href=\"/zh/docs/18/runtime-config-query.html#RUNTIME-CONFIG-QUERY-CONSTANTS\"\u003e第 19.7.2 节\u003c/a\u003e）。传统上通常以磁盘页读取作为代价单位；也就是说，惯例上将 \u003ca class=\"xref\" href=\"/zh/docs/18/runtime-config-query.html#GUC-SEQ-PAGE-COST\"\u003eseq_page_cost\u003c/a\u003e 设为 \u003ccode class=\"literal\"\u003e1.0\u003c/code\u003e，其他代价参数都相对它来设定。本节中的示例都使用默认代价参数。\n   \u003c/p\u003e\u003cp\u003e\u003ca href=\"/zh/docs/18/using-explain.html#USING-EXPLAIN-BASICS\"\u003e查看完整中文手册与上下文\u003c/a\u003e。\u003c/p\u003e\u003cp\u003e本页开头的中文说明为 PG.CENTER 对编辑说明的翻译；手册节选保留对应版本中文文档原文。源码信息及手册示例不代表重新进行过运行测试。\u003c/p\u003e","evidence_kind":"source and documentation","explain_names":["Limit"],"explain_prefixes":["Parallel","Async"],"facts":[{"label":"Core node tag","value":"T_Limit"},{"label":"Structured EXPLAIN Node Type","value":"Limit"},{"label":"Inputs","value":"One child plan"},{"label":"Output","value":"The selected slice of tuples"},{"label":"Executor initializer","value":"ExecInitLimit"},{"label":"Memory mechanism","value":"unclassified"}],"facts_zh":[{"label":"核心节点标签","value":"T_Limit"},{"label":"结构化 EXPLAIN 节点类型","value":"Limit"},{"label":"输入","value":"一个子计划"},{"label":"输出","value":"选定范围的元组"},{"label":"执行器初始化函数","value":"ExecInitLimit"},{"label":"内存机制","value":"unclassified"}],"memory":{"description":"This extraction does not assign a universal memory limit or spill policy to this node. Inspect the same-build implementation and its expressions or provider.","evidence":[{"archive_sha256":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","label":"src/backend/executor/nodeLimit.c","path":"src/backend/executor/nodeLimit.c","sha256":"f4c202d7182d66c6bef222fa50439831691dd99bfa5fd6b4de7f9142635dc305","url":"https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2"}],"mechanism":"unclassified","source_notes":[]},"node_tag":"T_Limit","parallel_callbacks":[],"partial_modes":[],"related":[{"label":"EXPLAIN","url":"/wiki/sql/explain/?v=18"},{"label":"Using EXPLAIN","url":"/docs/18/using-explain.html"},{"label":"Parallel plans","url":"/docs/18/parallel-plans.html"}],"release":{"channel":"stable","label":"18.6","major":"18","ref":"PostgreSQL 18.6 source archive","revision":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","source_snapshot_utc":"","source_url":"https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2"},"runtime_verified":false,"sections":[{"paragraphs":["Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.","Text names recorded by this source: Limit.","Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node."],"title":"EXPLAIN names and attributes"},{"paragraphs":["This extraction does not assign a universal memory limit or spill policy to this node. Inspect the same-build implementation and its expressions or provider."],"title":"Memory and temporary storage"},{"paragraphs":["The source callbacks below can coordinate execution or collect worker instrumentation. Their presence is not a blanket claim that this node supports a shared parallel scan or shared state.","Callbacks in this build: none extracted from this node implementation."],"title":"Parallel execution and instrumentation"},{"paragraphs":["Estimated total cost. This is stated on the assumption that the plan node is run to completion, i.e., all available rows are retrieved. In practice a node's parent node might stop short of reading all available rows (see the LIMIT example below).","Compared to regular sorts, sorting incrementally allows returning tuples before the entire result set has been sorted, which particularly enables optimizations with LIMIT queries. It may also reduce memory usage and the likelihood of spilling sorts to disk, but it comes at the cost of the increased overhead of splitting the result set into multiple sorting batches.","This is the same query as above, but we added a LIMIT so that not all the rows need be retrieved, and the planner changed its mind about what to do. Notice that the total cost and row count of the Index Scan node are shown as if it were run to completion. However, the Limit node is expected to stop after retrieving only a fifth of those rows, so its total cost is only a fifth as much, and that's the actual estimated cost of the query. This plan is preferred over adding a Limit node to the previous plan because the Limit could not avoid paying the startup cost of the bitmap scan, so the total cost would be something over 25 units with that approach.","There are cases in which the actual and estimated values won't match up well, but nothing is really wrong. One such case occurs when plan node execution is stopped short by a LIMIT or similar effect. For example, in the LIMIT query we used before,","the estimated cost and row count for the Index Scan node are shown as though it were run to completion. But in reality the Limit node stopped requesting rows after it got two, so the actual row count is only 2 and the run time is less than the cost estimate would suggest. This is not an estimation error, only a discrepancy in the way the estimates and true values are displayed.","Merge joins also have measurement artifacts that can confuse the unwary. A merge join will stop reading one input if it's exhausted the other input and the next key value in the one input is greater than the last key value of the other input; in such a case there can be no more matches and so no need to scan the rest of the first input. This results in not reading all of one child, with results like those mentioned for LIMIT . Also, if the outer (first) child contains rows with duplicate key values, the inner (second) child is backed up and rescanned for the portion of its rows matching that key value. EXPLAIN ANALYZE counts these repeated emissions of the same inner rows as if they were real additional rows. When there are many outer duplicates, the reported actual row count for the inner child plan node can be significantly larger than the number of rows that are actually in the inner relation."],"title":"Same-version manual discussion"},{"blocks":[{"code":"EXPLAIN SELECT * FROM tenk1 ORDER BY hundred, ten LIMIT 100;\n\n                                              QUERY PLAN\n------------------------------------------------------------------------------------------------\n Limit  (cost=19.35..39.49 rows=100 width=244)\n   -\u003e  Incremental Sort  (cost=19.35..2033.39 rows=10000 width=244)\n         Sort Key: hundred, ten\n         Presorted Key: hundred\n         -\u003e  Index Scan using tenk1_hundred on tenk1  (cost=0.29..1574.20 rows=10000 width=244)","paragraphs":["Example copied from the PostgreSQL 18.6 manual; it was not executed for this collection.","If a part of the plan guarantees an ordering on a prefix of the required sort keys, then the planner may instead decide to use an Incremental Sort step:"],"source":{"label":"PostgreSQL 18.6 · using-explain","path":"using-explain.html","sha256":"60040c30180093418a0affe56dd27dff9df2504b705b38039589e458bf5c31ed","url":"/docs/18/using-explain.html#USING-EXPLAIN-BASICS"}},{"code":"EXPLAIN SELECT * FROM tenk1 WHERE unique1 \u003c 100 AND unique2 \u003e 9000 LIMIT 2;\n\n                                     QUERY PLAN\n-------------------------------------------------------------------------------------\n Limit  (cost=0.29..14.28 rows=2 width=244)\n   -\u003e  Index Scan using tenk1_unique2 on tenk1  (cost=0.29..70.27 rows=10 width=244)\n         Index Cond: (unique2 \u003e 9000)\n         Filter: (unique1 \u003c 100)","paragraphs":["Example copied from the PostgreSQL 18.6 manual; it was not executed for this collection.","Here is an example showing the effects of LIMIT :"],"source":{"label":"PostgreSQL 18.6 · using-explain","path":"using-explain.html","sha256":"60040c30180093418a0affe56dd27dff9df2504b705b38039589e458bf5c31ed","url":"/docs/18/using-explain.html#USING-EXPLAIN-BASICS"}}],"title":"Examples from this manual build"},{"paragraphs":["nodeLimit.c Routines to handle limiting of query results where appropriate","This is a very simple node which just performs LIMIT/OFFSET filtering on the stream of tuples returned by a subplan.","First call for this node, so compute limit/offset. (We can't do this any earlier, because parameters from upper nodes will not be set during ExecInitLimit.) This also sets position = 0 and changes the state to LIMIT_RESCAN.","The subplan returns too few tuples for us to produce any output at all.","Tuple at limit is needed for comparison in subsequent execution to detect ties."],"title":"Executor implementation notes"},{"code":"case T_Limit:\n\t\t\tpname = sname = \"Limit\";\n\t\t\tbreak;","title":"EXPLAIN identity in core source"}],"sections_zh":[{"paragraphs":["结构化格式使用上述 Node Type。文本格式名称还可能包含操作、策略、连接类型、扫描方向或聚合阶段属性。","此源码记录的文本名称：Limit.","并行感知与并行安全是不同的计划属性。在并行工作进程内运行的节点不一定是并行感知节点。"],"title":"EXPLAIN 名称与属性"},{"paragraphs":["本次抽取不为此节点设定统一的内存上限或落盘策略。请查看同一构建的实现、相关表达式或提供方。"],"title":"内存与临时存储"},{"paragraphs":["以下源码回调可以协调执行或收集工作进程的测量数据。回调存在不代表该节点普遍支持共享并行扫描或共享状态。","此构建的回调：none extracted from this node implementation."],"title":"并行执行与运行信息采集"},{"paragraphs":["估计总代价：假定计划节点完整执行，即取出所有可用行时的代价。实际执行时，父节点可能尚未读取全部可用行就提前停止（见下方 LIMIT 示例）。","与普通排序相比，增量排序可在整个结果集尚未排完时就返回元组，尤其有利于优化带 LIMIT 的查询。它还可能减少内存用量和排序溢写磁盘的概率，但代价是将结果集拆成多个排序批次所带来的额外开销。","查询与上例相同，只是增加 LIMIT，不再需要取回全部行，因此规划器改变了选择。Index Scan 节点的总成本和行数仍按完整执行显示，但 Limit 预计只取回五分之一的行就停止，其总成本也只有五分之一，这才是查询的实际估计成本。与在此前计划上添加 Limit 相比，此计划更优，因为 Limit 无法避免位图扫描的启动成本，原方案的总成本仍会超过 25 个单位。","实际值与估计值有时并不吻合，但并不表示有问题。例如 LIMIT 或类似作用提前停止计划节点执行时就会如此。以前面的 LIMIT 查询为例：","Index Scan 节点的估计成本和行数按完整执行显示。但实际执行中，Limit 在取得两行后就不再请求，因此实际行数仅为 2，运行时间也低于成本估计所暗示的值。这不是估计错误，只是估计值与实际值的展示口径不同。","归并连接的测量结果也可能产生误导。若一侧输入已耗尽，另一侧的下一个键值又大于已耗尽输入的最后一个键值，就不会再有匹配，因此会停止读取另一侧。这样便未读取该子节点的全部行，类似 LIMIT 的情况。另外，外侧（第一个）子节点有重复键值时，内侧（第二个）子节点会回退并重新扫描匹配该键值的行。EXPLAIN ANALYZE 会将内侧重复输出的行计作额外的真实行。因此外侧重复值很多时，内侧计划节点报告的实际行数可能显著超过内侧关系中的实际行数。"],"title":"同版本手册说明"},{"blocks":[{"code":"EXPLAIN SELECT * FROM tenk1 ORDER BY hundred, ten LIMIT 100;\n\n                                              QUERY PLAN\n------------------------------------------------------------------------------------------------\n Limit  (cost=19.35..39.49 rows=100 width=244)\n   -\u003e  Incremental Sort  (cost=19.35..2033.39 rows=10000 width=244)\n         Sort Key: hundred, ten\n         Presorted Key: hundred\n         -\u003e  Index Scan using tenk1_hundred on tenk1  (cost=0.29..1574.20 rows=10000 width=244)","paragraphs":["示例摘自 PostgreSQL 18.6 手册；本百科未实际执行此示例。","如果计划中的某一部分已经保证了所需排序键前缀的顺序，规划器也可能改用 Incremental Sort 步骤："],"source":{"label":"PostgreSQL 18.6 · using-explain","path":"using-explain.html","sha256":"60040c30180093418a0affe56dd27dff9df2504b705b38039589e458bf5c31ed","url":"/docs/18/using-explain.html#USING-EXPLAIN-BASICS"}},{"code":"EXPLAIN SELECT * FROM tenk1 WHERE unique1 \u003c 100 AND unique2 \u003e 9000 LIMIT 2;\n\n                                     QUERY PLAN\n-------------------------------------------------------------------------------------\n Limit  (cost=0.29..14.28 rows=2 width=244)\n   -\u003e  Index Scan using tenk1_unique2 on tenk1  (cost=0.29..70.27 rows=10 width=244)\n         Index Cond: (unique2 \u003e 9000)\n         Filter: (unique1 \u003c 100)","paragraphs":["示例摘自 PostgreSQL 18.6 手册；本百科未实际执行此示例。","下面的示例展示 LIMIT 的作用："],"source":{"label":"PostgreSQL 18.6 · using-explain","path":"using-explain.html","sha256":"60040c30180093418a0affe56dd27dff9df2504b705b38039589e458bf5c31ed","url":"/docs/18/using-explain.html#USING-EXPLAIN-BASICS"}}],"title":"本版手册中的示例"},{"paragraphs":["nodeLimit.c：在适当情况下限制查询结果的例程。","这是一个非常简单的节点，仅对某个子计划返回的元组流执行 LIMIT/OFFSET 筛选。","首次调用此节点，因此计算 limit/offset。（不能更早计算，因为 ExecInitLimit 阶段尚未设置上层节点传来的参数。）这还会设置 position = 0，并将状态改为 LIMIT_RESCAN。","子计划返回的元组太少，无法产生任何输出。","需要保存边界处的元组，以在后续执行中比较并识别并列值。"],"title":"执行器实现说明"},{"code":"case T_Limit:\n\t\t\tpname = sname = \"Limit\";\n\t\t\tbreak;","title":"核心源码中的 EXPLAIN 标识"}],"source_inventory":{"executor":"src/backend/executor/execProcnode.c","explain":"src/backend/commands/explain.c","implementation":"src/backend/executor/nodeLimit.c"},"sources":[{"archive_sha256":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","label":"src/backend/commands/explain.c:1601","line":1601,"path":"src/backend/commands/explain.c","sha256":"34c86d6070224a0e981efef51f79101d6d505e5874f1684ace183034bab14bb4","url":"https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2"},{"archive_sha256":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","label":"src/backend/executor/execProcnode.c:380","line":380,"path":"src/backend/executor/execProcnode.c","sha256":"f8a06a3f539077249b20664b2812433db6d7bd12b2c0ca633525db43d06f112a","url":"https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2"},{"archive_sha256":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","label":"src/backend/executor/nodeLimit.c","path":"src/backend/executor/nodeLimit.c","sha256":"f4c202d7182d66c6bef222fa50439831691dd99bfa5fd6b4de7f9142635dc305","url":"https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2"},{"archive_sha256":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","label":"src/include/nodes/plannodes.h","path":"src/include/nodes/plannodes.h","sha256":"52422b327a8049fbbb20d8b96008a0fc0a6fafa60f7eff3c695d5b2e83830120","url":"https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2"},{"label":"PostgreSQL 18.6 · using-explain","path":"using-explain.html","sha256":"60040c30180093418a0affe56dd27dff9df2504b705b38039589e458bf5c31ed","url":"/docs/18/using-explain.html#USING-EXPLAIN-BASICS"},{"label":"PostgreSQL 18.6 · using-explain","path":"using-explain.html","sha256":"60040c30180093418a0affe56dd27dff9df2504b705b38039589e458bf5c31ed","url":"/docs/18/using-explain.html#USING-EXPLAIN-CAVEATS"}],"strategies":[],"tables":[{"columns":[{"key":"label","label":"Text-format label"},{"key":"identity","label":"Structured node identity"}],"key":"explain-labels","rows":[{"identity":"Limit","label":"Limit"}],"title":"EXPLAIN labels in this source build"}],"tables_zh":[{"columns":[{"key":"label","label":"文本格式标签"},{"key":"identity","label":"结构化节点标识"}],"key":"explain-labels","rows":[{"identity":"Limit","label":"Limit"}],"title":"本构建中的 EXPLAIN 标签"}],"zh_from":{"authored_translation":"authored-translation-of-reviewed-guidance","body_sha256":"8e377f6658ad70efca8f693e49aad39c78dd2ee1677efe373862e6a794d1681e","kind":"same-version-chinese-manual-with-authored-translation-of-reviewed-guidance","manual":{"anchor":"USING-EXPLAIN-BASICS","build_id":107,"extraction":"concept-introduction","fragment_sha256":"bc79b6f9c70f2b56968e08ea26d2c9ec3d395e425aca0594e227203daa0ad29b","locale":"zh-Hans","page_key":"using-explain.html","source_hash":"d2f749744b3ac5aa2eb0154f295e8163903cd20fcc130c74c6172cdf2ae3a9df","source_revision":"unknown:rendered-translation-baseline","translated_from_revision":null,"translation_revision":"git:b1b500221dbe5437cfca004d6b04d3f6e422765d;html-sha256:08e987a66af27b98444a8057c256314eafa13611a3fb9e888214fc436824244b","url":"/zh/docs/18/using-explain.html#USING-EXPLAIN-BASICS","version":"18"},"runtime_rerun":false,"source_facts_revision":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}},"ManualEvidence":{"release":{"channel":"stable","label":"18.6","major":"18","ref":"PostgreSQL 18.6 source archive","revision":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","source_snapshot_utc":"","source_url":"https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2"},"sources":[{"archive_sha256":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","label":"src/backend/commands/explain.c:1601","line":1601,"path":"src/backend/commands/explain.c","sha256":"34c86d6070224a0e981efef51f79101d6d505e5874f1684ace183034bab14bb4","url":"https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2"},{"archive_sha256":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","label":"src/backend/executor/execProcnode.c:380","line":380,"path":"src/backend/executor/execProcnode.c","sha256":"f8a06a3f539077249b20664b2812433db6d7bd12b2c0ca633525db43d06f112a","url":"https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2"},{"archive_sha256":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","label":"src/backend/executor/nodeLimit.c","path":"src/backend/executor/nodeLimit.c","sha256":"f4c202d7182d66c6bef222fa50439831691dd99bfa5fd6b4de7f9142635dc305","url":"https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2"},{"archive_sha256":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","label":"src/include/nodes/plannodes.h","path":"src/include/nodes/plannodes.h","sha256":"52422b327a8049fbbb20d8b96008a0fc0a6fafa60f7eff3c695d5b2e83830120","url":"https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2"},{"label":"PostgreSQL 18.6 · using-explain","path":"using-explain.html","sha256":"60040c30180093418a0affe56dd27dff9df2504b705b38039589e458bf5c31ed","url":"/docs/18/using-explain.html#USING-EXPLAIN-BASICS"},{"label":"PostgreSQL 18.6 · using-explain","path":"using-explain.html","sha256":"60040c30180093418a0affe56dd27dff9df2504b705b38039589e458bf5c31ed","url":"/docs/18/using-explain.html#USING-EXPLAIN-CAVEATS"}]},"MeasuredEvidence":{"runtime_verified":false}},"Text":{"Collection":"plan","Key":"limit","SourceDatabase":"center","Version":"18","Locale":"en","Title":"Limit","Summary":"Applies the plan row-count and offset bounds to its child output.","BodyHTML":"\u003cp\u003eApplies the plan row-count and offset bounds to its child output.\u003c/p\u003e","SourceRevision":"555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f","ContentHash":"7df0b42259fdfbaa347961125366888dfdd3a416f5040476f3b9deadbaf2a6bd","Payload":{"description":["Applies the plan row-count and offset bounds to its child output."],"related":[{"label":"EXPLAIN","url":"/wiki/sql/explain/?v=18"},{"label":"Using EXPLAIN","url":"/docs/18/using-explain.html"},{"label":"Parallel plans","url":"/docs/18/parallel-plans.html"}],"sections":[{"paragraphs":["Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.","Text names recorded by this source: Limit.","Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node."],"title":"EXPLAIN names and attributes"},{"paragraphs":["This extraction does not assign a universal memory limit or spill policy to this node. Inspect the same-build implementation and its expressions or provider."],"title":"Memory and temporary storage"},{"paragraphs":["The source callbacks below can coordinate execution or collect worker instrumentation. Their presence is not a blanket claim that this node supports a shared parallel scan or shared state.","Callbacks in this build: none extracted from this node implementation."],"title":"Parallel execution and instrumentation"},{"paragraphs":["Estimated total cost. This is stated on the assumption that the plan node is run to completion, i.e., all available rows are retrieved. In practice a node's parent node might stop short of reading all available rows (see the LIMIT example below).","Compared to regular sorts, sorting incrementally allows returning tuples before the entire result set has been sorted, which particularly enables optimizations with LIMIT queries. It may also reduce memory usage and the likelihood of spilling sorts to disk, but it comes at the cost of the increased overhead of splitting the result set into multiple sorting batches.","This is the same query as above, but we added a LIMIT so that not all the rows need be retrieved, and the planner changed its mind about what to do. Notice that the total cost and row count of the Index Scan node are shown as if it were run to completion. However, the Limit node is expected to stop after retrieving only a fifth of those rows, so its total cost is only a fifth as much, and that's the actual estimated cost of the query. This plan is preferred over adding a Limit node to the previous plan because the Limit could not avoid paying the startup cost of the bitmap scan, so the total cost would be something over 25 units with that approach.","There are cases in which the actual and estimated values won't match up well, but nothing is really wrong. One such case occurs when plan node execution is stopped short by a LIMIT or similar effect. For example, in the LIMIT query we used before,","the estimated cost and row count for the Index Scan node are shown as though it were run to completion. But in reality the Limit node stopped requesting rows after it got two, so the actual row count is only 2 and the run time is less than the cost estimate would suggest. This is not an estimation error, only a discrepancy in the way the estimates and true values are displayed.","Merge joins also have measurement artifacts that can confuse the unwary. A merge join will stop reading one input if it's exhausted the other input and the next key value in the one input is greater than the last key value of the other input; in such a case there can be no more matches and so no need to scan the rest of the first input. This results in not reading all of one child, with results like those mentioned for LIMIT . Also, if the outer (first) child contains rows with duplicate key values, the inner (second) child is backed up and rescanned for the portion of its rows matching that key value. EXPLAIN ANALYZE counts these repeated emissions of the same inner rows as if they were real additional rows. When there are many outer duplicates, the reported actual row count for the inner child plan node can be significantly larger than the number of rows that are actually in the inner relation."],"title":"Same-version manual discussion"},{"blocks":[{"code":"EXPLAIN SELECT * FROM tenk1 ORDER BY hundred, ten LIMIT 100;\n\n                                              QUERY PLAN\n------------------------------------------------------------------------------------------------\n Limit  (cost=19.35..39.49 rows=100 width=244)\n   -\u003e  Incremental Sort  (cost=19.35..2033.39 rows=10000 width=244)\n         Sort Key: hundred, ten\n         Presorted Key: hundred\n         -\u003e  Index Scan using tenk1_hundred on tenk1  (cost=0.29..1574.20 rows=10000 width=244)","paragraphs":["Example copied from the PostgreSQL 18.6 manual; it was not executed for this collection.","If a part of the plan guarantees an ordering on a prefix of the required sort keys, then the planner may instead decide to use an Incremental Sort step:"],"source":{"label":"PostgreSQL 18.6 · using-explain","path":"using-explain.html","sha256":"60040c30180093418a0affe56dd27dff9df2504b705b38039589e458bf5c31ed","url":"/docs/18/using-explain.html#USING-EXPLAIN-BASICS"}},{"code":"EXPLAIN SELECT * FROM tenk1 WHERE unique1 \u003c 100 AND unique2 \u003e 9000 LIMIT 2;\n\n                                     QUERY PLAN\n-------------------------------------------------------------------------------------\n Limit  (cost=0.29..14.28 rows=2 width=244)\n   -\u003e  Index Scan using tenk1_unique2 on tenk1  (cost=0.29..70.27 rows=10 width=244)\n         Index Cond: (unique2 \u003e 9000)\n         Filter: (unique1 \u003c 100)","paragraphs":["Example copied from the PostgreSQL 18.6 manual; it was not executed for this collection.","Here is an example showing the effects of LIMIT :"],"source":{"label":"PostgreSQL 18.6 · using-explain","path":"using-explain.html","sha256":"60040c30180093418a0affe56dd27dff9df2504b705b38039589e458bf5c31ed","url":"/docs/18/using-explain.html#USING-EXPLAIN-BASICS"}}],"title":"Examples from this manual build"},{"paragraphs":["nodeLimit.c Routines to handle limiting of query results where appropriate","This is a very simple node which just performs LIMIT/OFFSET filtering on the stream of tuples returned by a subplan.","First call for this node, so compute limit/offset. (We can't do this any earlier, because parameters from upper nodes will not be set during ExecInitLimit.) This also sets position = 0 and changes the state to LIMIT_RESCAN.","The subplan returns too few tuples for us to produce any output at all.","Tuple at limit is needed for comparison in subsequent execution to detect ties."],"title":"Executor implementation notes"},{"code":"case T_Limit:\n\t\t\tpname = sname = \"Limit\";\n\t\t\tbreak;","title":"EXPLAIN identity in core source"}],"tables":[{"columns":[{"key":"label","label":"Text-format label"},{"key":"identity","label":"Structured node identity"}],"key":"explain-labels","rows":[{"identity":"Limit","label":"Limit"}],"title":"EXPLAIN labels in this source build"}]}},"RequestedLocale":"en","Fallback":false,"Versions":["10","11","12","13","14","15","16","17","18","19","20"],"Locales":["en","zh-Hans"],"Signatures":null,"Spellings":null,"SQLState":null,"Evidence":null}
