{"kind": "plan", "major": "18", "item": {"slug": "incremental-sort", "name": "Incremental Sort", "name_zh": "IncrementalSort", "category": "\u6392\u5e8f", "summary": "\u5bf9\u5171\u4eab\u5df2\u6709\u6392\u5e8f\u952e\u524d\u7f00\u7684\u5206\u7ec4\u5206\u522b\u6392\u5e8f\uff0c\u6269\u5c55\u8f93\u5165\u5df2\u6709\u7684\u6392\u5e8f\u987a\u5e8f\u3002", "aliases": ["Incremental Sort", "IncrementalSort", "T_IncrementalSort"], "content_hash": "fea9b2a33b3971ab0556c0578ce00245278438c05e149ad4bd0cfec9b2c5b14b", "versions": {"13": {"facts": [{"label": "\u6838\u5fc3\u8282\u70b9\u6807\u7b7e", "value": "T_IncrementalSort"}, {"label": "\u7ed3\u6784\u5316 EXPLAIN \u8282\u70b9\u7c7b\u578b", "value": "Incremental Sort"}, {"label": "\u8f93\u5165", "value": "\u4e00\u4e2a\u90e8\u5206\u6709\u5e8f\u7684\u5b50\u8ba1\u5212"}, {"label": "\u8f93\u51fa", "value": "\u6309\u5b8c\u6574\u6392\u5e8f\u952e\u6392\u5e8f\u7684\u5143\u7ec4"}, {"label": "\u6267\u884c\u5668\u521d\u59cb\u5316\u51fd\u6570", "value": "ExecInitIncrementalSort"}, {"label": "\u5185\u5b58\u673a\u5236", "value": "tuplesort"}], "memory": {"evidence": [{"url": "https://ftp.postgresql.org/pub/source/v13.23/postgresql-13.23.tar.bz2", "path": "src/backend/executor/nodeIncrementalSort.c", "label": "src/backend/executor/nodeIncrementalSort.c", "sha256": "5cb475d6fe29f28797ab003948a74e949352c107b85350bbab70b8ae7131fd0d", "archive_sha256": "6ec3c82726af92b7dec873fa1cdf881eca92a4219787dfad05acb6b10e041fd6"}, {"url": "https://ftp.postgresql.org/pub/source/v13.23/postgresql-13.23.tar.bz2", "path": "src/backend/utils/sort/tuplesort.c", "label": "src/backend/utils/sort/tuplesort.c", "sha256": "87afe1e79fcca02b36d021c770db27a3990194a4697718fb11c83ea5696aad95", "archive_sha256": "6ec3c82726af92b7dec873fa1cdf881eca92a4219787dfad05acb6b10e041fd6"}], "mechanism": "tuplesort", "description": "\u6b64\u8282\u70b9\u5c06 work_mem \u4f20\u7ed9 tuplesort\u3002\u6392\u5e8f\u53ef\u4f7f\u7528\u5185\u5b58\u6216\u4e34\u65f6\u6587\u4ef6\uff1b\u5b9e\u9645\u65b9\u6cd5\u548c\u7a7a\u95f4\u7528\u91cf\u53d6\u51b3\u4e8e\u8f93\u5165\u53ca\u8ba1\u5212\u3002", "source_notes": ["Incremental sort may be more efficient than plain sort, particularly on large datasets, as it reduces the amount of data to sort at once, making it more likely it fits into work_mem (eliminating the need to spill to disk). But the main advantage of incremental sort is that it can start producing rows early, before sorting the whole dataset, which is a significant benefit especially for queries with LIMIT.", "Because incremental sort processes (potentially many) sort batches, we need to capture tuplesort stats each time we finalize a sort state. This summary data is later used for EXPLAIN ANALYZE output."]}, "tables": [{"key": "explain-labels", "rows": [{"label": "Incremental Sort", "identity": "Incremental Sort"}], "title": "\u672c\u6784\u5efa\u4e2d\u7684 EXPLAIN \u6807\u7b7e", "columns": [{"key": "label", "label": "\u6587\u672c\u683c\u5f0f\u6807\u7b7e"}, {"key": "identity", "label": "\u7ed3\u6784\u5316\u8282\u70b9\u6807\u8bc6"}]}], "related": [{"url": "/wiki/sql/explain/?v=13", "label": "EXPLAIN"}, {"url": "/docs/13/using-explain.html", "label": "\u4f7f\u7528 EXPLAIN"}, {"url": "/docs/13/parallel-plans.html", "label": "\u5e76\u884c\u8ba1\u5212"}, {"url": "/wiki/guc/enable_incremental_sort/?v=13", "label": "enable_incremental_sort"}, {"url": "/wiki/guc/work_mem/?v=13", "label": "work_mem"}], "release": {"ref": "PostgreSQL 13.23 source archive", "label": "13.23", "major": "13", "channel": "historical", "revision": "6ec3c82726af92b7dec873fa1cdf881eca92a4219787dfad05acb6b10e041fd6", "source_url": "https://ftp.postgresql.org/pub/source/v13.23/postgresql-13.23.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v13.23/postgresql-13.23.tar.bz2", "line": 1273, "path": "src/backend/commands/explain.c", "label": "src/backend/commands/explain.c:1273", "sha256": "541713e0e7f1c9cc352c2b6028964d440c19d2678a4463000094c24a88c1e730", "archive_sha256": "6ec3c82726af92b7dec873fa1cdf881eca92a4219787dfad05acb6b10e041fd6"}, {"url": "https://ftp.postgresql.org/pub/source/v13.23/postgresql-13.23.tar.bz2", "line": 318, "path": "src/backend/executor/execProcnode.c", "label": "src/backend/executor/execProcnode.c:318", "sha256": "d085ee99acfa00587e6ade3a1d9f8108a0566beedbbee3f54a50c9fc0cc2e875", "archive_sha256": "6ec3c82726af92b7dec873fa1cdf881eca92a4219787dfad05acb6b10e041fd6"}, {"url": "https://ftp.postgresql.org/pub/source/v13.23/postgresql-13.23.tar.bz2", "path": "src/backend/executor/nodeIncrementalSort.c", "label": "src/backend/executor/nodeIncrementalSort.c", "sha256": "5cb475d6fe29f28797ab003948a74e949352c107b85350bbab70b8ae7131fd0d", "archive_sha256": "6ec3c82726af92b7dec873fa1cdf881eca92a4219787dfad05acb6b10e041fd6"}, {"url": "https://ftp.postgresql.org/pub/source/v13.23/postgresql-13.23.tar.bz2", "path": "src/include/nodes/plannodes.h", "label": "src/include/nodes/plannodes.h", "sha256": "dcb296833777b02008c4b6bae8e8f7c6423b7ffba21f36702597c9d596d039ab", "archive_sha256": "6ec3c82726af92b7dec873fa1cdf881eca92a4219787dfad05acb6b10e041fd6"}, {"url": "https://ftp.postgresql.org/pub/source/v13.23/postgresql-13.23.tar.bz2", "path": "src/backend/utils/sort/tuplesort.c", "label": "src/backend/utils/sort/tuplesort.c", "sha256": "87afe1e79fcca02b36d021c770db27a3990194a4697718fb11c83ea5696aad95", "archive_sha256": "6ec3c82726af92b7dec873fa1cdf881eca92a4219787dfad05acb6b10e041fd6"}, {"url": "https://pg.center/docs/13/using-explain.html#USING-EXPLAIN-BASICS", "path": "using-explain.html", "label": "PostgreSQL 13.23 \u00b7 using-explain", "sha256": "650fd8629382d5dc8f9f8412c50ec5f32442a9ad2f98ca88e5348a7c2bd0ac7a", "language": "en", "original_url": "/docs/13/using-explain.html#USING-EXPLAIN-BASICS"}], "node_tag": "T_IncrementalSort", "sections": [{"title": "EXPLAIN \u540d\u79f0\u4e0e\u5c5e\u6027", "paragraphs": ["\u7ed3\u6784\u5316\u683c\u5f0f\u4f7f\u7528\u4e0a\u8ff0 Node Type\u3002\u6587\u672c\u683c\u5f0f\u540d\u79f0\u8fd8\u53ef\u80fd\u5305\u542b\u64cd\u4f5c\u3001\u7b56\u7565\u3001\u8fde\u63a5\u7c7b\u578b\u3001\u626b\u63cf\u65b9\u5411\u6216\u805a\u5408\u9636\u6bb5\u5c5e\u6027\u3002", "\u6b64\u6e90\u7801\u8bb0\u5f55\u7684\u6587\u672c\u540d\u79f0\uff1aIncremental Sort.", "\u5e76\u884c\u611f\u77e5\u4e0e\u5e76\u884c\u5b89\u5168\u662f\u4e0d\u540c\u7684\u8ba1\u5212\u5c5e\u6027\u3002\u5728\u5e76\u884c\u5de5\u4f5c\u8fdb\u7a0b\u5185\u8fd0\u884c\u7684\u8282\u70b9\u4e0d\u4e00\u5b9a\u662f\u5e76\u884c\u611f\u77e5\u8282\u70b9\u3002"]}, {"title": "\u5185\u5b58\u4e0e\u4e34\u65f6\u5b58\u50a8", "paragraphs": ["\u6b64\u8282\u70b9\u5c06 work_mem \u4f20\u7ed9 tuplesort\u3002\u6392\u5e8f\u53ef\u4f7f\u7528\u5185\u5b58\u6216\u4e34\u65f6\u6587\u4ef6\uff1b\u5b9e\u9645\u65b9\u6cd5\u548c\u7a7a\u95f4\u7528\u91cf\u53d6\u51b3\u4e8e\u8f93\u5165\u53ca\u8ba1\u5212\u3002", "\u589e\u91cf\u6392\u5e8f\u53ef\u80fd\u6bd4\u666e\u901a\u6392\u5e8f\u66f4\u9ad8\u6548\uff0c\u5c24\u5176\u5bf9\u4e8e\u5927\u578b\u6570\u636e\u96c6\uff0c\u56e0\u4e3a\u5b83\u51cf\u5c11\u4e86\u6bcf\u6b21\u6392\u5e8f\u7684\u6570\u636e\u91cf\uff0c\u66f4\u53ef\u80fd\u653e\u5165 work_mem\uff0c\u4ece\u800c\u907f\u514d\u843d\u76d8\u3002\u4f46\u5176\u4e3b\u8981\u4f18\u52bf\u662f\u5728\u6574\u4e2a\u6570\u636e\u96c6\u6392\u5e8f\u5b8c\u6210\u4e4b\u524d\u5c31\u80fd\u5f00\u59cb\u8f93\u51fa\u884c\uff0c\u8fd9\u5bf9\u5e26 LIMIT \u7684\u67e5\u8be2\u5c24\u5176\u6709\u5229\u3002", "\u589e\u91cf\u6392\u5e8f\u53ef\u80fd\u5904\u7406\u8bb8\u591a\u6392\u5e8f\u6279\u6b21\uff0c\u56e0\u6b64\u6bcf\u6b21\u7ed3\u675f\u4e00\u4e2a\u6392\u5e8f\u72b6\u6001\u65f6\u90fd\u8981\u8bb0\u5f55 tuplesort \u7edf\u8ba1\u4fe1\u606f\u3002\u8fd9\u4e9b\u6c47\u603b\u6570\u636e\u968f\u540e\u7528\u4e8e EXPLAIN ANALYZE \u8f93\u51fa\u3002"]}, {"title": "\u5e76\u884c\u6267\u884c\u4e0e\u8fd0\u884c\u4fe1\u606f\u91c7\u96c6", "paragraphs": ["\u4ee5\u4e0b\u6e90\u7801\u56de\u8c03\u53ef\u4ee5\u534f\u8c03\u6267\u884c\u6216\u6536\u96c6\u5de5\u4f5c\u8fdb\u7a0b\u7684\u6d4b\u91cf\u6570\u636e\u3002\u56de\u8c03\u5b58\u5728\u4e0d\u4ee3\u8868\u8be5\u8282\u70b9\u666e\u904d\u652f\u6301\u5171\u4eab\u5e76\u884c\u626b\u63cf\u6216\u5171\u4eab\u72b6\u6001\u3002", "\u6b64\u6784\u5efa\u7684\u56de\u8c03\uff1aExecIncrementalSortEstimate, ExecIncrementalSortInitializeDSM, ExecIncrementalSortInitializeWorker, ExecIncrementalSortRetrieveInstrumentation."]}, {"title": "\u540c\u7248\u672c\u624b\u518c\u8bf4\u660e", "paragraphs": ["\u5982\u679c\u8ba1\u5212\u7684\u4e00\u90e8\u5206\u80fd\u4fdd\u8bc1\u8f93\u5165\u5df2\u6309\u6240\u9700\u6392\u5e8f\u952e\u7684\u524d\u7f00\u6392\u5e8f\uff0c\u89c4\u5212\u5668\u53ef\u80fd\u6539\u7528\u589e\u91cf\u6392\u5e8f\u6b65\u9aa4\uff1a"]}, {"title": "\u672c\u7248\u624b\u518c\u4e2d\u7684\u793a\u4f8b", "blocks": [{"code": "EXPLAIN SELECT * FROM tenk1 ORDER BY four, ten LIMIT 100;\n                                              QUERY PLAN\n------------------------------------------------------------------------------------------------------\n Limit  (cost=521.06..538.05 rows=100 width=244)\n   ->  Incremental Sort  (cost=521.06..2220.95 rows=10000 width=244)\n         Sort Key: four, ten\n         Presorted Key: four\n         ->  Index Scan using index_tenk1_on_four on tenk1  (cost=0.29..1510.08 rows=10000 width=244)", "source": {"url": "/docs/13/using-explain.html#USING-EXPLAIN-BASICS", "path": "using-explain.html", "label": "PostgreSQL 13.23 \u00b7 using-explain", "sha256": "650fd8629382d5dc8f9f8412c50ec5f32442a9ad2f98ca88e5348a7c2bd0ac7a"}, "paragraphs": ["\u793a\u4f8b\u6458\u81ea PostgreSQL 13.23 \u624b\u518c\uff1b\u672c\u767e\u79d1\u672a\u5b9e\u9645\u6267\u884c\u6b64\u793a\u4f8b\u3002", "\u5982\u679c\u8ba1\u5212\u7684\u4e00\u90e8\u5206\u80fd\u4fdd\u8bc1\u8f93\u5165\u5df2\u6309\u6240\u9700\u6392\u5e8f\u952e\u7684\u524d\u7f00\u6392\u5e8f\uff0c\u89c4\u5212\u5668\u53ef\u80fd\u6539\u7528\u589e\u91cf\u6392\u5e8f\u6b65\u9aa4\uff1a"]}]}, {"title": "\u6267\u884c\u5668\u5b9e\u73b0\u8bf4\u660e", "paragraphs": ["nodeIncrementalSort.c\uff1a\u5904\u7406\u5173\u7cfb\u589e\u91cf\u6392\u5e8f\u7684\u4f8b\u7a0b\u3002", "\u589e\u91cf\u6392\u5e8f\u662f\u591a\u952e\u6392\u5e8f\u7684\u4e00\u79cd\u4f18\u5316\u5f62\u5f0f\uff0c\u9002\u7528\u4e8e\u8f93\u5165\u5df2\u6309\u6392\u5e8f\u952e\u524d\u7f00\u6392\u597d\u5e8f\u7684\u60c5\u51b5\u3002\u4f8b\u5982\uff0c\u8981\u6c42\u6309 (key1, key2 ... keyN) \u6392\u5e8f\uff0c\u800c\u8f93\u5165\u5df2\u6309 (key1, key2 ... keyM) \u6392\u5e8f\uff0c\u4e14 M < N\uff0c\u5219\u53ef\u5c06\u8f93\u5165\u5212\u5206\u4e3a (key1, ... keyM) \u76f8\u7b49\u7684\u5206\u7ec4\uff0c\u53ea\u5bf9\u5269\u4f59\u5217\u6392\u5e8f\u3002", "\u8003\u8651\u4ee5\u4e0b\u793a\u4f8b\uff1a\u8f93\u5165\u5143\u7ec4\u7531\u4e24\u4e2a\u6574\u6570 (X, Y) \u7ec4\u6210\uff0c\u5df2\u7ecf\u6309 X \u9884\u6392\u5e8f\uff0c\u800c\u73b0\u5728\u9700\u8981\u540c\u65f6\u6309 X \u548c Y \u6392\u5e8f\u3002\u8f93\u5165\u5143\u7ec4\u5982\u4e0b\u3002", "\u589e\u91cf\u6392\u5e8f\u7b97\u6cd5\u4f1a\u6309 X \u76f8\u7b49\u5c06\u8f93\u5165\u62c6\u5206\u4e3a\u4ee5\u4e0b\u5404\u7ec4\uff0c\u518d\u5206\u522b\u6309 Y \u6392\u5e8f\uff1a", "\u5bf9\u8fd9\u4e9b\u5206\u7ec4\u5206\u522b\u6392\u5e8f\u540e\uff0c\u5c06\u5176\u62fc\u63a5\u8d77\u6765\uff0c\u5373\u53ef\u5f97\u5230\u4e0b\u9762\u6309\u8981\u6c42\u540c\u65f6\u6309 X \u548c Y \u6392\u5e8f\u7684\u7ed3\u679c\uff1a"]}, {"code": "case T_IncrementalSort:\n\t\t\tpname = sname = \"Incremental Sort\";\n\t\t\tbreak;", "title": "\u6838\u5fc3\u6e90\u7801\u4e2d\u7684 EXPLAIN \u6807\u8bc6"}], "strategies": [], "description": ["\u5bf9\u5171\u4eab\u5df2\u6709\u6392\u5e8f\u952e\u524d\u7f00\u7684\u5206\u7ec4\u5206\u522b\u6392\u5e8f\uff0c\u6269\u5c55\u8f93\u5165\u5df2\u6709\u7684\u6392\u5e8f\u987a\u5e8f\u3002"], "localization": {"status": "complete", "sources": [], "language": "zh", "original_text": {"/versions/13/description/0": "Extends an existing ordering by sorting groups that share the presorted key prefix.", "/versions/13/facts/0/label": "Core node tag", "/versions/13/facts/1/label": "Structured EXPLAIN Node Type", "/versions/13/facts/2/label": "Inputs", "/versions/13/facts/2/value": "One partly ordered child plan", "/versions/13/facts/3/label": "Output", "/versions/13/facts/3/value": "Tuples ordered by the full sort key", "/versions/13/facts/4/label": "Executor initializer", "/versions/13/facts/5/label": "Memory mechanism", "/versions/13/tables/0/title": "EXPLAIN labels in this source build", "/versions/13/related/1/label": "Using EXPLAIN", "/versions/13/related/2/label": "Parallel plans", "/versions/13/sections/0/title": "EXPLAIN names and attributes", "/versions/13/sections/1/title": "Memory and temporary storage", "/versions/13/sections/2/title": "Parallel execution and instrumentation", "/versions/13/sections/3/title": "Same-version manual discussion", "/versions/13/sections/4/title": "Examples from this manual build", "/versions/13/sections/5/title": "Executor implementation notes", "/versions/13/sections/6/title": "EXPLAIN identity in core source", "/versions/13/memory/description": "The node passes work_mem to tuplesort. Sorting can use memory or temporary files; the actual method and space use depend on the input and plan.", "/versions/13/sections/0/paragraphs/0": "Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.", "/versions/13/sections/0/paragraphs/1": "Text names recorded by this source: Incremental Sort.", "/versions/13/sections/0/paragraphs/2": "Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node.", "/versions/13/sections/1/paragraphs/0": "The node passes work_mem to tuplesort. Sorting can use memory or temporary files; the actual method and space use depend on the input and plan.", "/versions/13/sections/1/paragraphs/1": "Incremental sort may be more efficient than plain sort, particularly on large datasets, as it reduces the amount of data to sort at once, making it more likely it fits into work_mem (eliminating the need to spill to disk). But the main advantage of incremental sort is that it can start producing rows early, before sorting the whole dataset, which is a significant benefit especially for queries with LIMIT.", "/versions/13/sections/1/paragraphs/2": "Because incremental sort processes (potentially many) sort batches, we need to capture tuplesort stats each time we finalize a sort state. This summary data is later used for EXPLAIN ANALYZE output.", "/versions/13/sections/2/paragraphs/0": "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.", "/versions/13/sections/2/paragraphs/1": "Callbacks in this build: ExecIncrementalSortEstimate, ExecIncrementalSortInitializeDSM, ExecIncrementalSortInitializeWorker, ExecIncrementalSortRetrieveInstrumentation.", "/versions/13/sections/3/paragraphs/0": "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:", "/versions/13/sections/5/paragraphs/0": "nodeIncrementalSort.c Routines to handle incremental sorting of relations.", "/versions/13/sections/5/paragraphs/1": "Incremental sort is an optimized variant of multikey sort for cases when the input is already sorted by a prefix of the sort keys. For example when a sort by (key1, key2 ... keyN) is requested, and the input is already sorted by (key1, key2 ... keyM), M < N, we can divide the input into groups where keys (key1, ... keyM) are equal, and only sort on the remaining columns.", "/versions/13/sections/5/paragraphs/2": "Consider the following example. We have input tuples consisting of two integers (X, Y) already presorted by X, while it's required to sort them by both X and Y. Let input tuples be following.", "/versions/13/sections/5/paragraphs/3": "An incremental sort algorithm would split the input into the following groups, which have equal X, and then sort them by Y individually:", "/versions/13/sections/5/paragraphs/4": "After sorting these groups and putting them altogether, we would get the following result which is sorted by X and Y, as requested:", "/versions/13/tables/0/columns/0/label": "Text-format label", "/versions/13/tables/0/columns/1/label": "Structured node identity", "/versions/13/sections/4/blocks/0/paragraphs/0": "Example copied from the PostgreSQL 13.23 manual; it was not executed for this collection.", "/versions/13/sections/4/blocks/0/paragraphs/1": "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:"}, "fallback_fields": [], "source_language": "en", "original_snapshot_sha256": "f687c263fa0e599ed0bcf7bc1e0ea97ea68b5d1533a7d44abda7927e153f5b47"}, "evidence_kind": "source and documentation", "explain_names": ["Incremental Sort"], "partial_modes": [], "comparison_data": {"node_tag": "T_IncrementalSort", "strategies": [], "text_names": ["Incremental Sort"], "initializer": "ExecInitIncrementalSort", "partial_modes": [], "memory_mechanism": "tuplesort", "parallel_callbacks": ["ExecIncrementalSortEstimate", "ExecIncrementalSortInitializeDSM", "ExecIncrementalSortInitializeWorker", "ExecIncrementalSortRetrieveInstrumentation"]}, "comparison_hash": "28d8e33452af10dcac50fa98fa4c5c6f639be663ae15b475f003e7c287e678f4", "explain_prefixes": ["Parallel"], "runtime_verified": false, "source_inventory": {"explain": "src/backend/commands/explain.c", "executor": "src/backend/executor/execProcnode.c", "implementation": "src/backend/executor/nodeIncrementalSort.c"}, "parallel_callbacks": ["ExecIncrementalSortEstimate", "ExecIncrementalSortInitializeDSM", "ExecIncrementalSortInitializeWorker", "ExecIncrementalSortRetrieveInstrumentation"]}, "14": {"facts": [{"label": "\u6838\u5fc3\u8282\u70b9\u6807\u7b7e", "value": "T_IncrementalSort"}, {"label": "\u7ed3\u6784\u5316 EXPLAIN \u8282\u70b9\u7c7b\u578b", "value": "Incremental Sort"}, {"label": "\u8f93\u5165", "value": "\u4e00\u4e2a\u90e8\u5206\u6709\u5e8f\u7684\u5b50\u8ba1\u5212"}, {"label": "\u8f93\u51fa", "value": "\u6309\u5b8c\u6574\u6392\u5e8f\u952e\u6392\u5e8f\u7684\u5143\u7ec4"}, {"label": "\u6267\u884c\u5668\u521d\u59cb\u5316\u51fd\u6570", "value": "ExecInitIncrementalSort"}, {"label": "\u5185\u5b58\u673a\u5236", "value": "tuplesort"}], "memory": {"evidence": [{"url": "https://ftp.postgresql.org/pub/source/v14.24/postgresql-14.24.tar.bz2", "path": "src/backend/executor/nodeIncrementalSort.c", "label": "src/backend/executor/nodeIncrementalSort.c", "sha256": "8705649ad03491b97581648930bf21fecc4c3886b5ca98c8e1e46cd46ea1f8d7", "archive_sha256": "a7fa7ed3d558172355f51406097a7bd4f6b473be80f311ef7cda96bf383d8897"}, {"url": "https://ftp.postgresql.org/pub/source/v14.24/postgresql-14.24.tar.bz2", "path": "src/backend/utils/sort/tuplesort.c", "label": "src/backend/utils/sort/tuplesort.c", "sha256": "2fd22829081aaa010d5026ea7d1cbff1a3b721d6a5210cae58b9a3d5992d9745", "archive_sha256": "a7fa7ed3d558172355f51406097a7bd4f6b473be80f311ef7cda96bf383d8897"}], "mechanism": "tuplesort", "description": "\u6b64\u8282\u70b9\u5c06 work_mem \u4f20\u7ed9 tuplesort\u3002\u6392\u5e8f\u53ef\u4f7f\u7528\u5185\u5b58\u6216\u4e34\u65f6\u6587\u4ef6\uff1b\u5b9e\u9645\u65b9\u6cd5\u548c\u7a7a\u95f4\u7528\u91cf\u53d6\u51b3\u4e8e\u8f93\u5165\u53ca\u8ba1\u5212\u3002", "source_notes": ["Incremental sort may be more efficient than plain sort, particularly on large datasets, as it reduces the amount of data to sort at once, making it more likely it fits into work_mem (eliminating the need to spill to disk). But the main advantage of incremental sort is that it can start producing rows early, before sorting the whole dataset, which is a significant benefit especially for queries with LIMIT.", "Because incremental sort processes (potentially many) sort batches, we need to capture tuplesort stats each time we finalize a sort state. This summary data is later used for EXPLAIN ANALYZE output."]}, "tables": [{"key": "explain-labels", "rows": [{"label": "Incremental Sort", "identity": "Incremental Sort"}], "title": "\u672c\u6784\u5efa\u4e2d\u7684 EXPLAIN \u6807\u7b7e", "columns": [{"key": "label", "label": "\u6587\u672c\u683c\u5f0f\u6807\u7b7e"}, {"key": "identity", "label": "\u7ed3\u6784\u5316\u8282\u70b9\u6807\u8bc6"}]}], "related": [{"url": "/wiki/sql/explain/?v=14", "label": "EXPLAIN"}, {"url": "/docs/14/using-explain.html", "label": "\u4f7f\u7528 EXPLAIN"}, {"url": "/docs/14/parallel-plans.html", "label": "\u5e76\u884c\u8ba1\u5212"}, {"url": "/wiki/guc/enable_incremental_sort/?v=14", "label": "enable_incremental_sort"}, {"url": "/wiki/guc/work_mem/?v=14", "label": "work_mem"}], "release": {"ref": "PostgreSQL 14.24 source archive", "label": "14.24", "major": "14", "channel": "stable", "revision": "a7fa7ed3d558172355f51406097a7bd4f6b473be80f311ef7cda96bf383d8897", "source_url": "https://ftp.postgresql.org/pub/source/v14.24/postgresql-14.24.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v14.24/postgresql-14.24.tar.bz2", "line": 1315, "path": "src/backend/commands/explain.c", "label": "src/backend/commands/explain.c:1315", "sha256": "e091be4e2a083b8dea39ccd09beedede22c1716ef974da66c214a44f48be8c41", "archive_sha256": "a7fa7ed3d558172355f51406097a7bd4f6b473be80f311ef7cda96bf383d8897"}, {"url": "https://ftp.postgresql.org/pub/source/v14.24/postgresql-14.24.tar.bz2", "line": 325, "path": "src/backend/executor/execProcnode.c", "label": "src/backend/executor/execProcnode.c:325", "sha256": "72da1c5ad457f1d92a39ab73531701794df858419e3b89d6e6cb7079634e68fa", "archive_sha256": "a7fa7ed3d558172355f51406097a7bd4f6b473be80f311ef7cda96bf383d8897"}, {"url": "https://ftp.postgresql.org/pub/source/v14.24/postgresql-14.24.tar.bz2", "path": "src/backend/executor/nodeIncrementalSort.c", "label": "src/backend/executor/nodeIncrementalSort.c", "sha256": "8705649ad03491b97581648930bf21fecc4c3886b5ca98c8e1e46cd46ea1f8d7", "archive_sha256": "a7fa7ed3d558172355f51406097a7bd4f6b473be80f311ef7cda96bf383d8897"}, {"url": "https://ftp.postgresql.org/pub/source/v14.24/postgresql-14.24.tar.bz2", "path": "src/include/nodes/plannodes.h", "label": "src/include/nodes/plannodes.h", "sha256": "302f51a16b570dba7ec4e7bc045f7df5800d21630280354d1a24025f3baec75d", "archive_sha256": "a7fa7ed3d558172355f51406097a7bd4f6b473be80f311ef7cda96bf383d8897"}, {"url": "https://ftp.postgresql.org/pub/source/v14.24/postgresql-14.24.tar.bz2", "path": "src/backend/utils/sort/tuplesort.c", "label": "src/backend/utils/sort/tuplesort.c", "sha256": "2fd22829081aaa010d5026ea7d1cbff1a3b721d6a5210cae58b9a3d5992d9745", "archive_sha256": "a7fa7ed3d558172355f51406097a7bd4f6b473be80f311ef7cda96bf383d8897"}, {"url": "https://pg.center/docs/14/using-explain.html#USING-EXPLAIN-BASICS", "path": "using-explain.html", "label": "PostgreSQL 14.24 \u00b7 using-explain", "sha256": "7f5ab59cb21a035ada45ea3426c5d1cca3f781273483677f73fdd76753555206", "language": "en", "original_url": "/docs/14/using-explain.html#USING-EXPLAIN-BASICS"}], "node_tag": "T_IncrementalSort", "sections": [{"title": "EXPLAIN \u540d\u79f0\u4e0e\u5c5e\u6027", "paragraphs": ["\u7ed3\u6784\u5316\u683c\u5f0f\u4f7f\u7528\u4e0a\u8ff0 Node Type\u3002\u6587\u672c\u683c\u5f0f\u540d\u79f0\u8fd8\u53ef\u80fd\u5305\u542b\u64cd\u4f5c\u3001\u7b56\u7565\u3001\u8fde\u63a5\u7c7b\u578b\u3001\u626b\u63cf\u65b9\u5411\u6216\u805a\u5408\u9636\u6bb5\u5c5e\u6027\u3002", "\u6b64\u6e90\u7801\u8bb0\u5f55\u7684\u6587\u672c\u540d\u79f0\uff1aIncremental Sort.", "\u5e76\u884c\u611f\u77e5\u4e0e\u5e76\u884c\u5b89\u5168\u662f\u4e0d\u540c\u7684\u8ba1\u5212\u5c5e\u6027\u3002\u5728\u5e76\u884c\u5de5\u4f5c\u8fdb\u7a0b\u5185\u8fd0\u884c\u7684\u8282\u70b9\u4e0d\u4e00\u5b9a\u662f\u5e76\u884c\u611f\u77e5\u8282\u70b9\u3002"]}, {"title": "\u5185\u5b58\u4e0e\u4e34\u65f6\u5b58\u50a8", "paragraphs": ["\u6b64\u8282\u70b9\u5c06 work_mem \u4f20\u7ed9 tuplesort\u3002\u6392\u5e8f\u53ef\u4f7f\u7528\u5185\u5b58\u6216\u4e34\u65f6\u6587\u4ef6\uff1b\u5b9e\u9645\u65b9\u6cd5\u548c\u7a7a\u95f4\u7528\u91cf\u53d6\u51b3\u4e8e\u8f93\u5165\u53ca\u8ba1\u5212\u3002", "\u589e\u91cf\u6392\u5e8f\u53ef\u80fd\u6bd4\u666e\u901a\u6392\u5e8f\u66f4\u9ad8\u6548\uff0c\u5c24\u5176\u5bf9\u4e8e\u5927\u578b\u6570\u636e\u96c6\uff0c\u56e0\u4e3a\u5b83\u51cf\u5c11\u4e86\u6bcf\u6b21\u6392\u5e8f\u7684\u6570\u636e\u91cf\uff0c\u66f4\u53ef\u80fd\u653e\u5165 work_mem\uff0c\u4ece\u800c\u907f\u514d\u843d\u76d8\u3002\u4f46\u5176\u4e3b\u8981\u4f18\u52bf\u662f\u5728\u6574\u4e2a\u6570\u636e\u96c6\u6392\u5e8f\u5b8c\u6210\u4e4b\u524d\u5c31\u80fd\u5f00\u59cb\u8f93\u51fa\u884c\uff0c\u8fd9\u5bf9\u5e26 LIMIT \u7684\u67e5\u8be2\u5c24\u5176\u6709\u5229\u3002", "\u589e\u91cf\u6392\u5e8f\u53ef\u80fd\u5904\u7406\u8bb8\u591a\u6392\u5e8f\u6279\u6b21\uff0c\u56e0\u6b64\u6bcf\u6b21\u7ed3\u675f\u4e00\u4e2a\u6392\u5e8f\u72b6\u6001\u65f6\u90fd\u8981\u8bb0\u5f55 tuplesort \u7edf\u8ba1\u4fe1\u606f\u3002\u8fd9\u4e9b\u6c47\u603b\u6570\u636e\u968f\u540e\u7528\u4e8e EXPLAIN ANALYZE \u8f93\u51fa\u3002"]}, {"title": "\u5e76\u884c\u6267\u884c\u4e0e\u8fd0\u884c\u4fe1\u606f\u91c7\u96c6", "paragraphs": ["\u4ee5\u4e0b\u6e90\u7801\u56de\u8c03\u53ef\u4ee5\u534f\u8c03\u6267\u884c\u6216\u6536\u96c6\u5de5\u4f5c\u8fdb\u7a0b\u7684\u6d4b\u91cf\u6570\u636e\u3002\u56de\u8c03\u5b58\u5728\u4e0d\u4ee3\u8868\u8be5\u8282\u70b9\u666e\u904d\u652f\u6301\u5171\u4eab\u5e76\u884c\u626b\u63cf\u6216\u5171\u4eab\u72b6\u6001\u3002", "\u6b64\u6784\u5efa\u7684\u56de\u8c03\uff1aExecIncrementalSortEstimate, ExecIncrementalSortInitializeDSM, ExecIncrementalSortInitializeWorker, ExecIncrementalSortRetrieveInstrumentation."]}, {"title": "\u540c\u7248\u672c\u624b\u518c\u8bf4\u660e", "paragraphs": ["\u5982\u679c\u8ba1\u5212\u7684\u4e00\u90e8\u5206\u80fd\u4fdd\u8bc1\u8f93\u5165\u5df2\u6309\u6240\u9700\u6392\u5e8f\u952e\u7684\u524d\u7f00\u6392\u5e8f\uff0c\u89c4\u5212\u5668\u53ef\u80fd\u6539\u7528\u589e\u91cf\u6392\u5e8f\u6b65\u9aa4\uff1a"]}, {"title": "\u672c\u7248\u624b\u518c\u4e2d\u7684\u793a\u4f8b", "blocks": [{"code": "EXPLAIN SELECT * FROM tenk1 ORDER BY four, ten LIMIT 100;\n                                              QUERY PLAN\n------------------------------------------------------------------------------------------------------\n Limit  (cost=521.06..538.05 rows=100 width=244)\n   ->  Incremental Sort  (cost=521.06..2220.95 rows=10000 width=244)\n         Sort Key: four, ten\n         Presorted Key: four\n         ->  Index Scan using index_tenk1_on_four on tenk1  (cost=0.29..1510.08 rows=10000 width=244)", "source": {"url": "/docs/14/using-explain.html#USING-EXPLAIN-BASICS", "path": "using-explain.html", "label": "PostgreSQL 14.24 \u00b7 using-explain", "sha256": "7f5ab59cb21a035ada45ea3426c5d1cca3f781273483677f73fdd76753555206"}, "paragraphs": ["\u793a\u4f8b\u6458\u81ea PostgreSQL 14.24 \u624b\u518c\uff1b\u672c\u767e\u79d1\u672a\u5b9e\u9645\u6267\u884c\u6b64\u793a\u4f8b\u3002", "\u5982\u679c\u8ba1\u5212\u7684\u4e00\u90e8\u5206\u80fd\u4fdd\u8bc1\u8f93\u5165\u5df2\u6309\u6240\u9700\u6392\u5e8f\u952e\u7684\u524d\u7f00\u6392\u5e8f\uff0c\u89c4\u5212\u5668\u53ef\u80fd\u6539\u7528\u589e\u91cf\u6392\u5e8f\u6b65\u9aa4\uff1a"]}]}, {"title": "\u6267\u884c\u5668\u5b9e\u73b0\u8bf4\u660e", "paragraphs": ["nodeIncrementalSort.c\uff1a\u5904\u7406\u5173\u7cfb\u589e\u91cf\u6392\u5e8f\u7684\u4f8b\u7a0b\u3002", "\u589e\u91cf\u6392\u5e8f\u662f\u591a\u952e\u6392\u5e8f\u7684\u4e00\u79cd\u4f18\u5316\u5f62\u5f0f\uff0c\u9002\u7528\u4e8e\u8f93\u5165\u5df2\u6309\u6392\u5e8f\u952e\u524d\u7f00\u6392\u597d\u5e8f\u7684\u60c5\u51b5\u3002\u4f8b\u5982\uff0c\u8981\u6c42\u6309 (key1, key2 ... keyN) \u6392\u5e8f\uff0c\u800c\u8f93\u5165\u5df2\u6309 (key1, key2 ... keyM) \u6392\u5e8f\uff0c\u4e14 M < N\uff0c\u5219\u53ef\u5c06\u8f93\u5165\u5212\u5206\u4e3a (key1, ... keyM) \u76f8\u7b49\u7684\u5206\u7ec4\uff0c\u53ea\u5bf9\u5269\u4f59\u5217\u6392\u5e8f\u3002", "\u8003\u8651\u4ee5\u4e0b\u793a\u4f8b\uff1a\u8f93\u5165\u5143\u7ec4\u7531\u4e24\u4e2a\u6574\u6570 (X, Y) \u7ec4\u6210\uff0c\u5df2\u7ecf\u6309 X \u9884\u6392\u5e8f\uff0c\u800c\u73b0\u5728\u9700\u8981\u540c\u65f6\u6309 X \u548c Y \u6392\u5e8f\u3002\u8f93\u5165\u5143\u7ec4\u5982\u4e0b\u3002", "\u589e\u91cf\u6392\u5e8f\u7b97\u6cd5\u4f1a\u6309 X \u76f8\u7b49\u5c06\u8f93\u5165\u62c6\u5206\u4e3a\u4ee5\u4e0b\u5404\u7ec4\uff0c\u518d\u5206\u522b\u6309 Y \u6392\u5e8f\uff1a", "\u5bf9\u8fd9\u4e9b\u5206\u7ec4\u5206\u522b\u6392\u5e8f\u540e\uff0c\u5c06\u5176\u62fc\u63a5\u8d77\u6765\uff0c\u5373\u53ef\u5f97\u5230\u4e0b\u9762\u6309\u8981\u6c42\u540c\u65f6\u6309 X \u548c Y \u6392\u5e8f\u7684\u7ed3\u679c\uff1a"]}, {"code": "case T_IncrementalSort:\n\t\t\tpname = sname = \"Incremental Sort\";\n\t\t\tbreak;", "title": "\u6838\u5fc3\u6e90\u7801\u4e2d\u7684 EXPLAIN \u6807\u8bc6"}], "strategies": [], "description": ["\u5bf9\u5171\u4eab\u5df2\u6709\u6392\u5e8f\u952e\u524d\u7f00\u7684\u5206\u7ec4\u5206\u522b\u6392\u5e8f\uff0c\u6269\u5c55\u8f93\u5165\u5df2\u6709\u7684\u6392\u5e8f\u987a\u5e8f\u3002"], "localization": {"status": "complete", "sources": [], "language": "zh", "original_text": {"/versions/14/description/0": "Extends an existing ordering by sorting groups that share the presorted key prefix.", "/versions/14/facts/0/label": "Core node tag", "/versions/14/facts/1/label": "Structured EXPLAIN Node Type", "/versions/14/facts/2/label": "Inputs", "/versions/14/facts/2/value": "One partly ordered child plan", "/versions/14/facts/3/label": "Output", "/versions/14/facts/3/value": "Tuples ordered by the full sort key", "/versions/14/facts/4/label": "Executor initializer", "/versions/14/facts/5/label": "Memory mechanism", "/versions/14/tables/0/title": "EXPLAIN labels in this source build", "/versions/14/related/1/label": "Using EXPLAIN", "/versions/14/related/2/label": "Parallel plans", "/versions/14/sections/0/title": "EXPLAIN names and attributes", "/versions/14/sections/1/title": "Memory and temporary storage", "/versions/14/sections/2/title": "Parallel execution and instrumentation", "/versions/14/sections/3/title": "Same-version manual discussion", "/versions/14/sections/4/title": "Examples from this manual build", "/versions/14/sections/5/title": "Executor implementation notes", "/versions/14/sections/6/title": "EXPLAIN identity in core source", "/versions/14/memory/description": "The node passes work_mem to tuplesort. Sorting can use memory or temporary files; the actual method and space use depend on the input and plan.", "/versions/14/sections/0/paragraphs/0": "Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.", "/versions/14/sections/0/paragraphs/1": "Text names recorded by this source: Incremental Sort.", "/versions/14/sections/0/paragraphs/2": "Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node.", "/versions/14/sections/1/paragraphs/0": "The node passes work_mem to tuplesort. Sorting can use memory or temporary files; the actual method and space use depend on the input and plan.", "/versions/14/sections/1/paragraphs/1": "Incremental sort may be more efficient than plain sort, particularly on large datasets, as it reduces the amount of data to sort at once, making it more likely it fits into work_mem (eliminating the need to spill to disk). But the main advantage of incremental sort is that it can start producing rows early, before sorting the whole dataset, which is a significant benefit especially for queries with LIMIT.", "/versions/14/sections/1/paragraphs/2": "Because incremental sort processes (potentially many) sort batches, we need to capture tuplesort stats each time we finalize a sort state. This summary data is later used for EXPLAIN ANALYZE output.", "/versions/14/sections/2/paragraphs/0": "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.", "/versions/14/sections/2/paragraphs/1": "Callbacks in this build: ExecIncrementalSortEstimate, ExecIncrementalSortInitializeDSM, ExecIncrementalSortInitializeWorker, ExecIncrementalSortRetrieveInstrumentation.", "/versions/14/sections/3/paragraphs/0": "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:", "/versions/14/sections/5/paragraphs/0": "nodeIncrementalSort.c Routines to handle incremental sorting of relations.", "/versions/14/sections/5/paragraphs/1": "Incremental sort is an optimized variant of multikey sort for cases when the input is already sorted by a prefix of the sort keys. For example when a sort by (key1, key2 ... keyN) is requested, and the input is already sorted by (key1, key2 ... keyM), M < N, we can divide the input into groups where keys (key1, ... keyM) are equal, and only sort on the remaining columns.", "/versions/14/sections/5/paragraphs/2": "Consider the following example. We have input tuples consisting of two integers (X, Y) already presorted by X, while it's required to sort them by both X and Y. Let input tuples be following.", "/versions/14/sections/5/paragraphs/3": "An incremental sort algorithm would split the input into the following groups, which have equal X, and then sort them by Y individually:", "/versions/14/sections/5/paragraphs/4": "After sorting these groups and putting them altogether, we would get the following result which is sorted by X and Y, as requested:", "/versions/14/tables/0/columns/0/label": "Text-format label", "/versions/14/tables/0/columns/1/label": "Structured node identity", "/versions/14/sections/4/blocks/0/paragraphs/0": "Example copied from the PostgreSQL 14.24 manual; it was not executed for this collection.", "/versions/14/sections/4/blocks/0/paragraphs/1": "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:"}, "fallback_fields": [], "source_language": "en", "original_snapshot_sha256": "4ea9af4499b48453ae5036df660683f8972ec7f933e9518bc9cb9d4ab93a78ab"}, "evidence_kind": "source and documentation", "explain_names": ["Incremental Sort"], "partial_modes": [], "comparison_data": {"node_tag": "T_IncrementalSort", "strategies": [], "text_names": ["Incremental Sort"], "initializer": "ExecInitIncrementalSort", "partial_modes": [], "memory_mechanism": "tuplesort", "parallel_callbacks": ["ExecIncrementalSortEstimate", "ExecIncrementalSortInitializeDSM", "ExecIncrementalSortInitializeWorker", "ExecIncrementalSortRetrieveInstrumentation"]}, "comparison_hash": "28d8e33452af10dcac50fa98fa4c5c6f639be663ae15b475f003e7c287e678f4", "explain_prefixes": ["Parallel", "Async"], "runtime_verified": false, "source_inventory": {"explain": "src/backend/commands/explain.c", "executor": "src/backend/executor/execProcnode.c", "implementation": "src/backend/executor/nodeIncrementalSort.c"}, "parallel_callbacks": ["ExecIncrementalSortEstimate", "ExecIncrementalSortInitializeDSM", "ExecIncrementalSortInitializeWorker", "ExecIncrementalSortRetrieveInstrumentation"]}, "15": {"facts": [{"label": "\u6838\u5fc3\u8282\u70b9\u6807\u7b7e", "value": "T_IncrementalSort"}, {"label": "\u7ed3\u6784\u5316 EXPLAIN \u8282\u70b9\u7c7b\u578b", "value": "Incremental Sort"}, {"label": "\u8f93\u5165", "value": "\u4e00\u4e2a\u90e8\u5206\u6709\u5e8f\u7684\u5b50\u8ba1\u5212"}, {"label": "\u8f93\u51fa", "value": "\u6309\u5b8c\u6574\u6392\u5e8f\u952e\u6392\u5e8f\u7684\u5143\u7ec4"}, {"label": "\u6267\u884c\u5668\u521d\u59cb\u5316\u51fd\u6570", "value": "ExecInitIncrementalSort"}, {"label": "\u5185\u5b58\u673a\u5236", "value": "tuplesort"}], "memory": {"evidence": [{"url": "https://ftp.postgresql.org/pub/source/v15.19/postgresql-15.19.tar.bz2", "path": "src/backend/executor/nodeIncrementalSort.c", "label": "src/backend/executor/nodeIncrementalSort.c", "sha256": "7a0c756cf22039c3619d23cacb891e456048748d11c0527db88914150ab3232e", "archive_sha256": "e1a64a87a46b825b88c082e4518161a47aab53c45694964f8ba1df28f7859f89"}, {"url": "https://ftp.postgresql.org/pub/source/v15.19/postgresql-15.19.tar.bz2", "path": "src/backend/utils/sort/tuplesort.c", "label": "src/backend/utils/sort/tuplesort.c", "sha256": "f1f95ed6d4bedca773aad26b93573b8b7b0c774b40560a1f4e21bd512d6530e4", "archive_sha256": "e1a64a87a46b825b88c082e4518161a47aab53c45694964f8ba1df28f7859f89"}], "mechanism": "tuplesort", "description": "\u6b64\u8282\u70b9\u5c06 work_mem \u4f20\u7ed9 tuplesort\u3002\u6392\u5e8f\u53ef\u4f7f\u7528\u5185\u5b58\u6216\u4e34\u65f6\u6587\u4ef6\uff1b\u5b9e\u9645\u65b9\u6cd5\u548c\u7a7a\u95f4\u7528\u91cf\u53d6\u51b3\u4e8e\u8f93\u5165\u53ca\u8ba1\u5212\u3002", "source_notes": ["Incremental sort may be more efficient than plain sort, particularly on large datasets, as it reduces the amount of data to sort at once, making it more likely it fits into work_mem (eliminating the need to spill to disk). But the main advantage of incremental sort is that it can start producing rows early, before sorting the whole dataset, which is a significant benefit especially for queries with LIMIT.", "Because incremental sort processes (potentially many) sort batches, we need to capture tuplesort stats each time we finalize a sort state. This summary data is later used for EXPLAIN ANALYZE output."]}, "tables": [{"key": "explain-labels", "rows": [{"label": "Incremental Sort", "identity": "Incremental Sort"}], "title": "\u672c\u6784\u5efa\u4e2d\u7684 EXPLAIN \u6807\u7b7e", "columns": [{"key": "label", "label": "\u6587\u672c\u683c\u5f0f\u6807\u7b7e"}, {"key": "identity", "label": "\u7ed3\u6784\u5316\u8282\u70b9\u6807\u8bc6"}]}], "related": [{"url": "/wiki/sql/explain/?v=15", "label": "EXPLAIN"}, {"url": "/docs/15/using-explain.html", "label": "\u4f7f\u7528 EXPLAIN"}, {"url": "/docs/15/parallel-plans.html", "label": "\u5e76\u884c\u8ba1\u5212"}, {"url": "/wiki/guc/enable_incremental_sort/?v=15", "label": "enable_incremental_sort"}, {"url": "/wiki/guc/work_mem/?v=15", "label": "work_mem"}], "release": {"ref": "PostgreSQL 15.19 source archive", "label": "15.19", "major": "15", "channel": "stable", "revision": "e1a64a87a46b825b88c082e4518161a47aab53c45694964f8ba1df28f7859f89", "source_url": "https://ftp.postgresql.org/pub/source/v15.19/postgresql-15.19.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v15.19/postgresql-15.19.tar.bz2", "line": 1318, "path": "src/backend/commands/explain.c", "label": "src/backend/commands/explain.c:1318", "sha256": "bb3b442d0f1b098aa8707335250102f027a596cd94117308bd16d1d36b258f5c", "archive_sha256": "e1a64a87a46b825b88c082e4518161a47aab53c45694964f8ba1df28f7859f89"}, {"url": "https://ftp.postgresql.org/pub/source/v15.19/postgresql-15.19.tar.bz2", "line": 325, "path": "src/backend/executor/execProcnode.c", "label": "src/backend/executor/execProcnode.c:325", "sha256": "19836c50a272741a4eac653541e655437c2e00710a541e5348d6a277d0669d7c", "archive_sha256": "e1a64a87a46b825b88c082e4518161a47aab53c45694964f8ba1df28f7859f89"}, {"url": "https://ftp.postgresql.org/pub/source/v15.19/postgresql-15.19.tar.bz2", "path": "src/backend/executor/nodeIncrementalSort.c", "label": "src/backend/executor/nodeIncrementalSort.c", "sha256": "7a0c756cf22039c3619d23cacb891e456048748d11c0527db88914150ab3232e", "archive_sha256": "e1a64a87a46b825b88c082e4518161a47aab53c45694964f8ba1df28f7859f89"}, {"url": "https://ftp.postgresql.org/pub/source/v15.19/postgresql-15.19.tar.bz2", "path": "src/include/nodes/plannodes.h", "label": "src/include/nodes/plannodes.h", "sha256": "fb4a4c8165495299131173680bc02a950d88e1ff610231fd97997bc0c9afc1d7", "archive_sha256": "e1a64a87a46b825b88c082e4518161a47aab53c45694964f8ba1df28f7859f89"}, {"url": "https://ftp.postgresql.org/pub/source/v15.19/postgresql-15.19.tar.bz2", "path": "src/backend/utils/sort/tuplesort.c", "label": "src/backend/utils/sort/tuplesort.c", "sha256": "f1f95ed6d4bedca773aad26b93573b8b7b0c774b40560a1f4e21bd512d6530e4", "archive_sha256": "e1a64a87a46b825b88c082e4518161a47aab53c45694964f8ba1df28f7859f89"}, {"url": "https://pg.center/docs/15/using-explain.html#USING-EXPLAIN-BASICS", "path": "using-explain.html", "label": "PostgreSQL 15.19 \u00b7 using-explain", "sha256": "d1f509457c647da453d2575c772d91022a0f115dd84f9a3b20f5ff25a243648f", "language": "en", "original_url": "/docs/15/using-explain.html#USING-EXPLAIN-BASICS"}], "node_tag": "T_IncrementalSort", "sections": [{"title": "EXPLAIN \u540d\u79f0\u4e0e\u5c5e\u6027", "paragraphs": ["\u7ed3\u6784\u5316\u683c\u5f0f\u4f7f\u7528\u4e0a\u8ff0 Node Type\u3002\u6587\u672c\u683c\u5f0f\u540d\u79f0\u8fd8\u53ef\u80fd\u5305\u542b\u64cd\u4f5c\u3001\u7b56\u7565\u3001\u8fde\u63a5\u7c7b\u578b\u3001\u626b\u63cf\u65b9\u5411\u6216\u805a\u5408\u9636\u6bb5\u5c5e\u6027\u3002", "\u6b64\u6e90\u7801\u8bb0\u5f55\u7684\u6587\u672c\u540d\u79f0\uff1aIncremental Sort.", "\u5e76\u884c\u611f\u77e5\u4e0e\u5e76\u884c\u5b89\u5168\u662f\u4e0d\u540c\u7684\u8ba1\u5212\u5c5e\u6027\u3002\u5728\u5e76\u884c\u5de5\u4f5c\u8fdb\u7a0b\u5185\u8fd0\u884c\u7684\u8282\u70b9\u4e0d\u4e00\u5b9a\u662f\u5e76\u884c\u611f\u77e5\u8282\u70b9\u3002"]}, {"title": "\u5185\u5b58\u4e0e\u4e34\u65f6\u5b58\u50a8", "paragraphs": ["\u6b64\u8282\u70b9\u5c06 work_mem \u4f20\u7ed9 tuplesort\u3002\u6392\u5e8f\u53ef\u4f7f\u7528\u5185\u5b58\u6216\u4e34\u65f6\u6587\u4ef6\uff1b\u5b9e\u9645\u65b9\u6cd5\u548c\u7a7a\u95f4\u7528\u91cf\u53d6\u51b3\u4e8e\u8f93\u5165\u53ca\u8ba1\u5212\u3002", "\u589e\u91cf\u6392\u5e8f\u53ef\u80fd\u6bd4\u666e\u901a\u6392\u5e8f\u66f4\u9ad8\u6548\uff0c\u5c24\u5176\u5bf9\u4e8e\u5927\u578b\u6570\u636e\u96c6\uff0c\u56e0\u4e3a\u5b83\u51cf\u5c11\u4e86\u6bcf\u6b21\u6392\u5e8f\u7684\u6570\u636e\u91cf\uff0c\u66f4\u53ef\u80fd\u653e\u5165 work_mem\uff0c\u4ece\u800c\u907f\u514d\u843d\u76d8\u3002\u4f46\u5176\u4e3b\u8981\u4f18\u52bf\u662f\u5728\u6574\u4e2a\u6570\u636e\u96c6\u6392\u5e8f\u5b8c\u6210\u4e4b\u524d\u5c31\u80fd\u5f00\u59cb\u8f93\u51fa\u884c\uff0c\u8fd9\u5bf9\u5e26 LIMIT \u7684\u67e5\u8be2\u5c24\u5176\u6709\u5229\u3002", "\u589e\u91cf\u6392\u5e8f\u53ef\u80fd\u5904\u7406\u8bb8\u591a\u6392\u5e8f\u6279\u6b21\uff0c\u56e0\u6b64\u6bcf\u6b21\u7ed3\u675f\u4e00\u4e2a\u6392\u5e8f\u72b6\u6001\u65f6\u90fd\u8981\u8bb0\u5f55 tuplesort \u7edf\u8ba1\u4fe1\u606f\u3002\u8fd9\u4e9b\u6c47\u603b\u6570\u636e\u968f\u540e\u7528\u4e8e EXPLAIN ANALYZE \u8f93\u51fa\u3002"]}, {"title": "\u5e76\u884c\u6267\u884c\u4e0e\u8fd0\u884c\u4fe1\u606f\u91c7\u96c6", "paragraphs": ["\u4ee5\u4e0b\u6e90\u7801\u56de\u8c03\u53ef\u4ee5\u534f\u8c03\u6267\u884c\u6216\u6536\u96c6\u5de5\u4f5c\u8fdb\u7a0b\u7684\u6d4b\u91cf\u6570\u636e\u3002\u56de\u8c03\u5b58\u5728\u4e0d\u4ee3\u8868\u8be5\u8282\u70b9\u666e\u904d\u652f\u6301\u5171\u4eab\u5e76\u884c\u626b\u63cf\u6216\u5171\u4eab\u72b6\u6001\u3002", "\u6b64\u6784\u5efa\u7684\u56de\u8c03\uff1aExecIncrementalSortEstimate, ExecIncrementalSortInitializeDSM, ExecIncrementalSortInitializeWorker, ExecIncrementalSortRetrieveInstrumentation."]}, {"title": "\u540c\u7248\u672c\u624b\u518c\u8bf4\u660e", "paragraphs": ["\u5982\u679c\u8ba1\u5212\u7684\u4e00\u90e8\u5206\u80fd\u4fdd\u8bc1\u8f93\u5165\u5df2\u6309\u6240\u9700\u6392\u5e8f\u952e\u7684\u524d\u7f00\u6392\u5e8f\uff0c\u89c4\u5212\u5668\u53ef\u80fd\u6539\u7528\u589e\u91cf\u6392\u5e8f\u6b65\u9aa4\uff1a"]}, {"title": "\u672c\u7248\u624b\u518c\u4e2d\u7684\u793a\u4f8b", "blocks": [{"code": "EXPLAIN SELECT * FROM tenk1 ORDER BY four, ten LIMIT 100;\n                                              QUERY PLAN\n------------------------------------------------------------------------------------------------------\n Limit  (cost=521.06..538.05 rows=100 width=244)\n   ->  Incremental Sort  (cost=521.06..2220.95 rows=10000 width=244)\n         Sort Key: four, ten\n         Presorted Key: four\n         ->  Index Scan using index_tenk1_on_four on tenk1  (cost=0.29..1510.08 rows=10000 width=244)", "source": {"url": "/docs/15/using-explain.html#USING-EXPLAIN-BASICS", "path": "using-explain.html", "label": "PostgreSQL 15.19 \u00b7 using-explain", "sha256": "d1f509457c647da453d2575c772d91022a0f115dd84f9a3b20f5ff25a243648f"}, "paragraphs": ["\u793a\u4f8b\u6458\u81ea PostgreSQL 15.19 \u624b\u518c\uff1b\u672c\u767e\u79d1\u672a\u5b9e\u9645\u6267\u884c\u6b64\u793a\u4f8b\u3002", "\u5982\u679c\u8ba1\u5212\u7684\u4e00\u90e8\u5206\u80fd\u4fdd\u8bc1\u8f93\u5165\u5df2\u6309\u6240\u9700\u6392\u5e8f\u952e\u7684\u524d\u7f00\u6392\u5e8f\uff0c\u89c4\u5212\u5668\u53ef\u80fd\u6539\u7528\u589e\u91cf\u6392\u5e8f\u6b65\u9aa4\uff1a"]}]}, {"title": "\u6267\u884c\u5668\u5b9e\u73b0\u8bf4\u660e", "paragraphs": ["nodeIncrementalSort.c\uff1a\u5904\u7406\u5173\u7cfb\u589e\u91cf\u6392\u5e8f\u7684\u4f8b\u7a0b\u3002", "\u589e\u91cf\u6392\u5e8f\u662f\u591a\u952e\u6392\u5e8f\u7684\u4e00\u79cd\u4f18\u5316\u5f62\u5f0f\uff0c\u9002\u7528\u4e8e\u8f93\u5165\u5df2\u6309\u6392\u5e8f\u952e\u524d\u7f00\u6392\u597d\u5e8f\u7684\u60c5\u51b5\u3002\u4f8b\u5982\uff0c\u8981\u6c42\u6309 (key1, key2 ... keyN) \u6392\u5e8f\uff0c\u800c\u8f93\u5165\u5df2\u6309 (key1, key2 ... keyM) \u6392\u5e8f\uff0c\u4e14 M < N\uff0c\u5219\u53ef\u5c06\u8f93\u5165\u5212\u5206\u4e3a (key1, ... keyM) \u76f8\u7b49\u7684\u5206\u7ec4\uff0c\u53ea\u5bf9\u5269\u4f59\u5217\u6392\u5e8f\u3002", "\u8003\u8651\u4ee5\u4e0b\u793a\u4f8b\uff1a\u8f93\u5165\u5143\u7ec4\u7531\u4e24\u4e2a\u6574\u6570 (X, Y) \u7ec4\u6210\uff0c\u5df2\u7ecf\u6309 X \u9884\u6392\u5e8f\uff0c\u800c\u73b0\u5728\u9700\u8981\u540c\u65f6\u6309 X \u548c Y \u6392\u5e8f\u3002\u8f93\u5165\u5143\u7ec4\u5982\u4e0b\u3002", "\u589e\u91cf\u6392\u5e8f\u7b97\u6cd5\u4f1a\u6309 X \u76f8\u7b49\u5c06\u8f93\u5165\u62c6\u5206\u4e3a\u4ee5\u4e0b\u5404\u7ec4\uff0c\u518d\u5206\u522b\u6309 Y \u6392\u5e8f\uff1a", "\u5bf9\u8fd9\u4e9b\u5206\u7ec4\u5206\u522b\u6392\u5e8f\u540e\uff0c\u5c06\u5176\u62fc\u63a5\u8d77\u6765\uff0c\u5373\u53ef\u5f97\u5230\u4e0b\u9762\u6309\u8981\u6c42\u540c\u65f6\u6309 X \u548c Y \u6392\u5e8f\u7684\u7ed3\u679c\uff1a"]}, {"code": "case T_IncrementalSort:\n\t\t\tpname = sname = \"Incremental Sort\";\n\t\t\tbreak;", "title": "\u6838\u5fc3\u6e90\u7801\u4e2d\u7684 EXPLAIN \u6807\u8bc6"}], "strategies": [], "description": ["\u5bf9\u5171\u4eab\u5df2\u6709\u6392\u5e8f\u952e\u524d\u7f00\u7684\u5206\u7ec4\u5206\u522b\u6392\u5e8f\uff0c\u6269\u5c55\u8f93\u5165\u5df2\u6709\u7684\u6392\u5e8f\u987a\u5e8f\u3002"], "localization": {"status": "complete", "sources": [], "language": "zh", "original_text": {"/versions/15/description/0": "Extends an existing ordering by sorting groups that share the presorted key prefix.", "/versions/15/facts/0/label": "Core node tag", "/versions/15/facts/1/label": "Structured EXPLAIN Node Type", "/versions/15/facts/2/label": "Inputs", "/versions/15/facts/2/value": "One partly ordered child plan", "/versions/15/facts/3/label": "Output", "/versions/15/facts/3/value": "Tuples ordered by the full sort key", "/versions/15/facts/4/label": "Executor initializer", "/versions/15/facts/5/label": "Memory mechanism", "/versions/15/tables/0/title": "EXPLAIN labels in this source build", "/versions/15/related/1/label": "Using EXPLAIN", "/versions/15/related/2/label": "Parallel plans", "/versions/15/sections/0/title": "EXPLAIN names and attributes", "/versions/15/sections/1/title": "Memory and temporary storage", "/versions/15/sections/2/title": "Parallel execution and instrumentation", "/versions/15/sections/3/title": "Same-version manual discussion", "/versions/15/sections/4/title": "Examples from this manual build", "/versions/15/sections/5/title": "Executor implementation notes", "/versions/15/sections/6/title": "EXPLAIN identity in core source", "/versions/15/memory/description": "The node passes work_mem to tuplesort. Sorting can use memory or temporary files; the actual method and space use depend on the input and plan.", "/versions/15/sections/0/paragraphs/0": "Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.", "/versions/15/sections/0/paragraphs/1": "Text names recorded by this source: Incremental Sort.", "/versions/15/sections/0/paragraphs/2": "Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node.", "/versions/15/sections/1/paragraphs/0": "The node passes work_mem to tuplesort. Sorting can use memory or temporary files; the actual method and space use depend on the input and plan.", "/versions/15/sections/1/paragraphs/1": "Incremental sort may be more efficient than plain sort, particularly on large datasets, as it reduces the amount of data to sort at once, making it more likely it fits into work_mem (eliminating the need to spill to disk). But the main advantage of incremental sort is that it can start producing rows early, before sorting the whole dataset, which is a significant benefit especially for queries with LIMIT.", "/versions/15/sections/1/paragraphs/2": "Because incremental sort processes (potentially many) sort batches, we need to capture tuplesort stats each time we finalize a sort state. This summary data is later used for EXPLAIN ANALYZE output.", "/versions/15/sections/2/paragraphs/0": "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.", "/versions/15/sections/2/paragraphs/1": "Callbacks in this build: ExecIncrementalSortEstimate, ExecIncrementalSortInitializeDSM, ExecIncrementalSortInitializeWorker, ExecIncrementalSortRetrieveInstrumentation.", "/versions/15/sections/3/paragraphs/0": "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:", "/versions/15/sections/5/paragraphs/0": "nodeIncrementalSort.c Routines to handle incremental sorting of relations.", "/versions/15/sections/5/paragraphs/1": "Incremental sort is an optimized variant of multikey sort for cases when the input is already sorted by a prefix of the sort keys. For example when a sort by (key1, key2 ... keyN) is requested, and the input is already sorted by (key1, key2 ... keyM), M < N, we can divide the input into groups where keys (key1, ... keyM) are equal, and only sort on the remaining columns.", "/versions/15/sections/5/paragraphs/2": "Consider the following example. We have input tuples consisting of two integers (X, Y) already presorted by X, while it's required to sort them by both X and Y. Let input tuples be following.", "/versions/15/sections/5/paragraphs/3": "An incremental sort algorithm would split the input into the following groups, which have equal X, and then sort them by Y individually:", "/versions/15/sections/5/paragraphs/4": "After sorting these groups and putting them altogether, we would get the following result which is sorted by X and Y, as requested:", "/versions/15/tables/0/columns/0/label": "Text-format label", "/versions/15/tables/0/columns/1/label": "Structured node identity", "/versions/15/sections/4/blocks/0/paragraphs/0": "Example copied from the PostgreSQL 15.19 manual; it was not executed for this collection.", "/versions/15/sections/4/blocks/0/paragraphs/1": "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:"}, "fallback_fields": [], "source_language": "en", "original_snapshot_sha256": "3d79c18486269415480d1dc1819c064ae7d09170fda8bc37661e473ce8b6b16b"}, "evidence_kind": "source and documentation", "explain_names": ["Incremental Sort"], "partial_modes": [], "comparison_data": {"node_tag": "T_IncrementalSort", "strategies": [], "text_names": ["Incremental Sort"], "initializer": "ExecInitIncrementalSort", "partial_modes": [], "memory_mechanism": "tuplesort", "parallel_callbacks": ["ExecIncrementalSortEstimate", "ExecIncrementalSortInitializeDSM", "ExecIncrementalSortInitializeWorker", "ExecIncrementalSortRetrieveInstrumentation"]}, "comparison_hash": "28d8e33452af10dcac50fa98fa4c5c6f639be663ae15b475f003e7c287e678f4", "explain_prefixes": ["Parallel", "Async"], "runtime_verified": false, "source_inventory": {"explain": "src/backend/commands/explain.c", "executor": "src/backend/executor/execProcnode.c", "implementation": "src/backend/executor/nodeIncrementalSort.c"}, "parallel_callbacks": ["ExecIncrementalSortEstimate", "ExecIncrementalSortInitializeDSM", "ExecIncrementalSortInitializeWorker", "ExecIncrementalSortRetrieveInstrumentation"]}, "16": {"facts": [{"label": "\u6838\u5fc3\u8282\u70b9\u6807\u7b7e", "value": "T_IncrementalSort"}, {"label": "\u7ed3\u6784\u5316 EXPLAIN \u8282\u70b9\u7c7b\u578b", "value": "Incremental Sort"}, {"label": "\u8f93\u5165", "value": "\u4e00\u4e2a\u90e8\u5206\u6709\u5e8f\u7684\u5b50\u8ba1\u5212"}, {"label": "\u8f93\u51fa", "value": "\u6309\u5b8c\u6574\u6392\u5e8f\u952e\u6392\u5e8f\u7684\u5143\u7ec4"}, {"label": "\u6267\u884c\u5668\u521d\u59cb\u5316\u51fd\u6570", "value": "ExecInitIncrementalSort"}, {"label": "\u5185\u5b58\u673a\u5236", "value": "tuplesort"}], "memory": {"evidence": [{"url": "https://ftp.postgresql.org/pub/source/v16.15/postgresql-16.15.tar.bz2", "path": "src/backend/executor/nodeIncrementalSort.c", "label": "src/backend/executor/nodeIncrementalSort.c", "sha256": "98399c0e70b54925985503c05398f162f95255a06d55b4acfec01f371fdb26b3", "archive_sha256": "c1575341fa7bd40f5274ea465b34390f4dc64cdd0770af327005caaeb9f6b7ed"}, {"url": "https://ftp.postgresql.org/pub/source/v16.15/postgresql-16.15.tar.bz2", "path": "src/backend/utils/sort/tuplesort.c", "label": "src/backend/utils/sort/tuplesort.c", "sha256": "cd9bf1be7bf73177a3c70e5daedd027c78d5ba8585652ed48750281e4af85af3", "archive_sha256": "c1575341fa7bd40f5274ea465b34390f4dc64cdd0770af327005caaeb9f6b7ed"}], "mechanism": "tuplesort", "description": "\u6b64\u8282\u70b9\u5c06 work_mem \u4f20\u7ed9 tuplesort\u3002\u6392\u5e8f\u53ef\u4f7f\u7528\u5185\u5b58\u6216\u4e34\u65f6\u6587\u4ef6\uff1b\u5b9e\u9645\u65b9\u6cd5\u548c\u7a7a\u95f4\u7528\u91cf\u53d6\u51b3\u4e8e\u8f93\u5165\u53ca\u8ba1\u5212\u3002", "source_notes": ["Incremental sort may be more efficient than plain sort, particularly on large datasets, as it reduces the amount of data to sort at once, making it more likely it fits into work_mem (eliminating the need to spill to disk). But the main advantage of incremental sort is that it can start producing rows early, before sorting the whole dataset, which is a significant benefit especially for queries with LIMIT.", "Because incremental sort processes (potentially many) sort batches, we need to capture tuplesort stats each time we finalize a sort state. This summary data is later used for EXPLAIN ANALYZE output."]}, "tables": [{"key": "explain-labels", "rows": [{"label": "Incremental Sort", "identity": "Incremental Sort"}], "title": "\u672c\u6784\u5efa\u4e2d\u7684 EXPLAIN \u6807\u7b7e", "columns": [{"key": "label", "label": "\u6587\u672c\u683c\u5f0f\u6807\u7b7e"}, {"key": "identity", "label": "\u7ed3\u6784\u5316\u8282\u70b9\u6807\u8bc6"}]}], "related": [{"url": "/wiki/sql/explain/?v=16", "label": "EXPLAIN"}, {"url": "/docs/16/using-explain.html", "label": "\u4f7f\u7528 EXPLAIN"}, {"url": "/docs/16/parallel-plans.html", "label": "\u5e76\u884c\u8ba1\u5212"}, {"url": "/wiki/guc/enable_incremental_sort/?v=16", "label": "enable_incremental_sort"}, {"url": "/wiki/guc/work_mem/?v=16", "label": "work_mem"}], "release": {"ref": "PostgreSQL 16.15 source archive", "label": "16.15", "major": "16", "channel": "stable", "revision": "c1575341fa7bd40f5274ea465b34390f4dc64cdd0770af327005caaeb9f6b7ed", "source_url": "https://ftp.postgresql.org/pub/source/v16.15/postgresql-16.15.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v16.15/postgresql-16.15.tar.bz2", "line": 1351, "path": "src/backend/commands/explain.c", "label": "src/backend/commands/explain.c:1351", "sha256": "8e017f0116dbea471339b40c37a667cc9f95039e7e0329c783e5e8ce194de7e1", "archive_sha256": "c1575341fa7bd40f5274ea465b34390f4dc64cdd0770af327005caaeb9f6b7ed"}, {"url": "https://ftp.postgresql.org/pub/source/v16.15/postgresql-16.15.tar.bz2", "line": 325, "path": "src/backend/executor/execProcnode.c", "label": "src/backend/executor/execProcnode.c:325", "sha256": "e48c08e555f8cb4e4bb43df516c4b8906ce9bc374b2a745d98a1fc8c22cc5099", "archive_sha256": "c1575341fa7bd40f5274ea465b34390f4dc64cdd0770af327005caaeb9f6b7ed"}, {"url": "https://ftp.postgresql.org/pub/source/v16.15/postgresql-16.15.tar.bz2", "path": "src/backend/executor/nodeIncrementalSort.c", "label": "src/backend/executor/nodeIncrementalSort.c", "sha256": "98399c0e70b54925985503c05398f162f95255a06d55b4acfec01f371fdb26b3", "archive_sha256": "c1575341fa7bd40f5274ea465b34390f4dc64cdd0770af327005caaeb9f6b7ed"}, {"url": "https://ftp.postgresql.org/pub/source/v16.15/postgresql-16.15.tar.bz2", "path": "src/include/nodes/plannodes.h", "label": "src/include/nodes/plannodes.h", "sha256": "97db47353db76326b874589a5ad0a04501cc74cd72e237e7bd956e7472c41f1f", "archive_sha256": "c1575341fa7bd40f5274ea465b34390f4dc64cdd0770af327005caaeb9f6b7ed"}, {"url": "https://ftp.postgresql.org/pub/source/v16.15/postgresql-16.15.tar.bz2", "path": "src/backend/utils/sort/tuplesort.c", "label": "src/backend/utils/sort/tuplesort.c", "sha256": "cd9bf1be7bf73177a3c70e5daedd027c78d5ba8585652ed48750281e4af85af3", "archive_sha256": "c1575341fa7bd40f5274ea465b34390f4dc64cdd0770af327005caaeb9f6b7ed"}, {"url": "https://pg.center/docs/16/using-explain.html#USING-EXPLAIN-BASICS", "path": "using-explain.html", "label": "PostgreSQL 16.15 \u00b7 using-explain", "sha256": "bd8b86e5281cf0e52ad6e0e4bb8b6ff6510dac61982b44f0c1dd07d54012db3c", "language": "en", "original_url": "/docs/16/using-explain.html#USING-EXPLAIN-BASICS"}], "node_tag": "T_IncrementalSort", "sections": [{"title": "EXPLAIN \u540d\u79f0\u4e0e\u5c5e\u6027", "paragraphs": ["\u7ed3\u6784\u5316\u683c\u5f0f\u4f7f\u7528\u4e0a\u8ff0 Node Type\u3002\u6587\u672c\u683c\u5f0f\u540d\u79f0\u8fd8\u53ef\u80fd\u5305\u542b\u64cd\u4f5c\u3001\u7b56\u7565\u3001\u8fde\u63a5\u7c7b\u578b\u3001\u626b\u63cf\u65b9\u5411\u6216\u805a\u5408\u9636\u6bb5\u5c5e\u6027\u3002", "\u6b64\u6e90\u7801\u8bb0\u5f55\u7684\u6587\u672c\u540d\u79f0\uff1aIncremental Sort.", "\u5e76\u884c\u611f\u77e5\u4e0e\u5e76\u884c\u5b89\u5168\u662f\u4e0d\u540c\u7684\u8ba1\u5212\u5c5e\u6027\u3002\u5728\u5e76\u884c\u5de5\u4f5c\u8fdb\u7a0b\u5185\u8fd0\u884c\u7684\u8282\u70b9\u4e0d\u4e00\u5b9a\u662f\u5e76\u884c\u611f\u77e5\u8282\u70b9\u3002"]}, {"title": "\u5185\u5b58\u4e0e\u4e34\u65f6\u5b58\u50a8", "paragraphs": ["\u6b64\u8282\u70b9\u5c06 work_mem \u4f20\u7ed9 tuplesort\u3002\u6392\u5e8f\u53ef\u4f7f\u7528\u5185\u5b58\u6216\u4e34\u65f6\u6587\u4ef6\uff1b\u5b9e\u9645\u65b9\u6cd5\u548c\u7a7a\u95f4\u7528\u91cf\u53d6\u51b3\u4e8e\u8f93\u5165\u53ca\u8ba1\u5212\u3002", "\u589e\u91cf\u6392\u5e8f\u53ef\u80fd\u6bd4\u666e\u901a\u6392\u5e8f\u66f4\u9ad8\u6548\uff0c\u5c24\u5176\u5bf9\u4e8e\u5927\u578b\u6570\u636e\u96c6\uff0c\u56e0\u4e3a\u5b83\u51cf\u5c11\u4e86\u6bcf\u6b21\u6392\u5e8f\u7684\u6570\u636e\u91cf\uff0c\u66f4\u53ef\u80fd\u653e\u5165 work_mem\uff0c\u4ece\u800c\u907f\u514d\u843d\u76d8\u3002\u4f46\u5176\u4e3b\u8981\u4f18\u52bf\u662f\u5728\u6574\u4e2a\u6570\u636e\u96c6\u6392\u5e8f\u5b8c\u6210\u4e4b\u524d\u5c31\u80fd\u5f00\u59cb\u8f93\u51fa\u884c\uff0c\u8fd9\u5bf9\u5e26 LIMIT \u7684\u67e5\u8be2\u5c24\u5176\u6709\u5229\u3002", "\u589e\u91cf\u6392\u5e8f\u53ef\u80fd\u5904\u7406\u8bb8\u591a\u6392\u5e8f\u6279\u6b21\uff0c\u56e0\u6b64\u6bcf\u6b21\u7ed3\u675f\u4e00\u4e2a\u6392\u5e8f\u72b6\u6001\u65f6\u90fd\u8981\u8bb0\u5f55 tuplesort \u7edf\u8ba1\u4fe1\u606f\u3002\u8fd9\u4e9b\u6c47\u603b\u6570\u636e\u968f\u540e\u7528\u4e8e EXPLAIN ANALYZE \u8f93\u51fa\u3002"]}, {"title": "\u5e76\u884c\u6267\u884c\u4e0e\u8fd0\u884c\u4fe1\u606f\u91c7\u96c6", "paragraphs": ["\u4ee5\u4e0b\u6e90\u7801\u56de\u8c03\u53ef\u4ee5\u534f\u8c03\u6267\u884c\u6216\u6536\u96c6\u5de5\u4f5c\u8fdb\u7a0b\u7684\u6d4b\u91cf\u6570\u636e\u3002\u56de\u8c03\u5b58\u5728\u4e0d\u4ee3\u8868\u8be5\u8282\u70b9\u666e\u904d\u652f\u6301\u5171\u4eab\u5e76\u884c\u626b\u63cf\u6216\u5171\u4eab\u72b6\u6001\u3002", "\u6b64\u6784\u5efa\u7684\u56de\u8c03\uff1aExecIncrementalSortEstimate, ExecIncrementalSortInitializeDSM, ExecIncrementalSortInitializeWorker, ExecIncrementalSortRetrieveInstrumentation."]}, {"title": "\u540c\u7248\u672c\u624b\u518c\u8bf4\u660e", "paragraphs": ["\u5982\u679c\u8ba1\u5212\u7684\u4e00\u90e8\u5206\u80fd\u4fdd\u8bc1\u8f93\u5165\u5df2\u6309\u6240\u9700\u6392\u5e8f\u952e\u7684\u524d\u7f00\u6392\u5e8f\uff0c\u89c4\u5212\u5668\u53ef\u80fd\u6539\u7528\u589e\u91cf\u6392\u5e8f\u6b65\u9aa4\uff1a"]}, {"title": "\u672c\u7248\u624b\u518c\u4e2d\u7684\u793a\u4f8b", "blocks": [{"code": "EXPLAIN SELECT * FROM tenk1 ORDER BY four, ten LIMIT 100;\n                                              QUERY PLAN\n------------------------------------------------------------------------------------------------------\n Limit  (cost=521.06..538.05 rows=100 width=244)\n   ->  Incremental Sort  (cost=521.06..2220.95 rows=10000 width=244)\n         Sort Key: four, ten\n         Presorted Key: four\n         ->  Index Scan using index_tenk1_on_four on tenk1  (cost=0.29..1510.08 rows=10000 width=244)", "source": {"url": "/docs/16/using-explain.html#USING-EXPLAIN-BASICS", "path": "using-explain.html", "label": "PostgreSQL 16.15 \u00b7 using-explain", "sha256": "bd8b86e5281cf0e52ad6e0e4bb8b6ff6510dac61982b44f0c1dd07d54012db3c"}, "paragraphs": ["\u793a\u4f8b\u6458\u81ea PostgreSQL 16.15 \u624b\u518c\uff1b\u672c\u767e\u79d1\u672a\u5b9e\u9645\u6267\u884c\u6b64\u793a\u4f8b\u3002", "\u5982\u679c\u8ba1\u5212\u7684\u4e00\u90e8\u5206\u80fd\u4fdd\u8bc1\u8f93\u5165\u5df2\u6309\u6240\u9700\u6392\u5e8f\u952e\u7684\u524d\u7f00\u6392\u5e8f\uff0c\u89c4\u5212\u5668\u53ef\u80fd\u6539\u7528\u589e\u91cf\u6392\u5e8f\u6b65\u9aa4\uff1a"]}]}, {"title": "\u6267\u884c\u5668\u5b9e\u73b0\u8bf4\u660e", "paragraphs": ["nodeIncrementalSort.c\uff1a\u5904\u7406\u5173\u7cfb\u589e\u91cf\u6392\u5e8f\u7684\u4f8b\u7a0b\u3002", "\u589e\u91cf\u6392\u5e8f\u662f\u591a\u952e\u6392\u5e8f\u7684\u4e00\u79cd\u4f18\u5316\u5f62\u5f0f\uff0c\u9002\u7528\u4e8e\u8f93\u5165\u5df2\u6309\u6392\u5e8f\u952e\u524d\u7f00\u6392\u597d\u5e8f\u7684\u60c5\u51b5\u3002\u4f8b\u5982\uff0c\u8981\u6c42\u6309 (key1, key2 ... keyN) \u6392\u5e8f\uff0c\u800c\u8f93\u5165\u5df2\u6309 (key1, key2 ... keyM) \u6392\u5e8f\uff0c\u4e14 M < N\uff0c\u5219\u53ef\u5c06\u8f93\u5165\u5212\u5206\u4e3a (key1, ... keyM) \u76f8\u7b49\u7684\u5206\u7ec4\uff0c\u53ea\u5bf9\u5269\u4f59\u5217\u6392\u5e8f\u3002", "\u8003\u8651\u4ee5\u4e0b\u793a\u4f8b\uff1a\u8f93\u5165\u5143\u7ec4\u7531\u4e24\u4e2a\u6574\u6570 (X, Y) \u7ec4\u6210\uff0c\u5df2\u7ecf\u6309 X \u9884\u6392\u5e8f\uff0c\u800c\u73b0\u5728\u9700\u8981\u540c\u65f6\u6309 X \u548c Y \u6392\u5e8f\u3002\u8f93\u5165\u5143\u7ec4\u5982\u4e0b\u3002", "\u589e\u91cf\u6392\u5e8f\u7b97\u6cd5\u4f1a\u6309 X \u76f8\u7b49\u5c06\u8f93\u5165\u62c6\u5206\u4e3a\u4ee5\u4e0b\u5404\u7ec4\uff0c\u518d\u5206\u522b\u6309 Y \u6392\u5e8f\uff1a", "\u5bf9\u8fd9\u4e9b\u5206\u7ec4\u5206\u522b\u6392\u5e8f\u540e\uff0c\u5c06\u5176\u62fc\u63a5\u8d77\u6765\uff0c\u5373\u53ef\u5f97\u5230\u4e0b\u9762\u6309\u8981\u6c42\u540c\u65f6\u6309 X \u548c Y \u6392\u5e8f\u7684\u7ed3\u679c\uff1a"]}, {"code": "case T_IncrementalSort:\n\t\t\tpname = sname = \"Incremental Sort\";\n\t\t\tbreak;", "title": "\u6838\u5fc3\u6e90\u7801\u4e2d\u7684 EXPLAIN \u6807\u8bc6"}], "strategies": [], "description": ["\u5bf9\u5171\u4eab\u5df2\u6709\u6392\u5e8f\u952e\u524d\u7f00\u7684\u5206\u7ec4\u5206\u522b\u6392\u5e8f\uff0c\u6269\u5c55\u8f93\u5165\u5df2\u6709\u7684\u6392\u5e8f\u987a\u5e8f\u3002"], "localization": {"status": "complete", "sources": [], "language": "zh", "original_text": {"/versions/16/description/0": "Extends an existing ordering by sorting groups that share the presorted key prefix.", "/versions/16/facts/0/label": "Core node tag", "/versions/16/facts/1/label": "Structured EXPLAIN Node Type", "/versions/16/facts/2/label": "Inputs", "/versions/16/facts/2/value": "One partly ordered child plan", "/versions/16/facts/3/label": "Output", "/versions/16/facts/3/value": "Tuples ordered by the full sort key", "/versions/16/facts/4/label": "Executor initializer", "/versions/16/facts/5/label": "Memory mechanism", "/versions/16/tables/0/title": "EXPLAIN labels in this source build", "/versions/16/related/1/label": "Using EXPLAIN", "/versions/16/related/2/label": "Parallel plans", "/versions/16/sections/0/title": "EXPLAIN names and attributes", "/versions/16/sections/1/title": "Memory and temporary storage", "/versions/16/sections/2/title": "Parallel execution and instrumentation", "/versions/16/sections/3/title": "Same-version manual discussion", "/versions/16/sections/4/title": "Examples from this manual build", "/versions/16/sections/5/title": "Executor implementation notes", "/versions/16/sections/6/title": "EXPLAIN identity in core source", "/versions/16/memory/description": "The node passes work_mem to tuplesort. Sorting can use memory or temporary files; the actual method and space use depend on the input and plan.", "/versions/16/sections/0/paragraphs/0": "Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.", "/versions/16/sections/0/paragraphs/1": "Text names recorded by this source: Incremental Sort.", "/versions/16/sections/0/paragraphs/2": "Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node.", "/versions/16/sections/1/paragraphs/0": "The node passes work_mem to tuplesort. Sorting can use memory or temporary files; the actual method and space use depend on the input and plan.", "/versions/16/sections/1/paragraphs/1": "Incremental sort may be more efficient than plain sort, particularly on large datasets, as it reduces the amount of data to sort at once, making it more likely it fits into work_mem (eliminating the need to spill to disk). But the main advantage of incremental sort is that it can start producing rows early, before sorting the whole dataset, which is a significant benefit especially for queries with LIMIT.", "/versions/16/sections/1/paragraphs/2": "Because incremental sort processes (potentially many) sort batches, we need to capture tuplesort stats each time we finalize a sort state. This summary data is later used for EXPLAIN ANALYZE output.", "/versions/16/sections/2/paragraphs/0": "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.", "/versions/16/sections/2/paragraphs/1": "Callbacks in this build: ExecIncrementalSortEstimate, ExecIncrementalSortInitializeDSM, ExecIncrementalSortInitializeWorker, ExecIncrementalSortRetrieveInstrumentation.", "/versions/16/sections/3/paragraphs/0": "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:", "/versions/16/sections/5/paragraphs/0": "nodeIncrementalSort.c Routines to handle incremental sorting of relations.", "/versions/16/sections/5/paragraphs/1": "Incremental sort is an optimized variant of multikey sort for cases when the input is already sorted by a prefix of the sort keys. For example when a sort by (key1, key2 ... keyN) is requested, and the input is already sorted by (key1, key2 ... keyM), M < N, we can divide the input into groups where keys (key1, ... keyM) are equal, and only sort on the remaining columns.", "/versions/16/sections/5/paragraphs/2": "Consider the following example. We have input tuples consisting of two integers (X, Y) already presorted by X, while it's required to sort them by both X and Y. Let input tuples be following.", "/versions/16/sections/5/paragraphs/3": "An incremental sort algorithm would split the input into the following groups, which have equal X, and then sort them by Y individually:", "/versions/16/sections/5/paragraphs/4": "After sorting these groups and putting them altogether, we would get the following result which is sorted by X and Y, as requested:", "/versions/16/tables/0/columns/0/label": "Text-format label", "/versions/16/tables/0/columns/1/label": "Structured node identity", "/versions/16/sections/4/blocks/0/paragraphs/0": "Example copied from the PostgreSQL 16.15 manual; it was not executed for this collection.", "/versions/16/sections/4/blocks/0/paragraphs/1": "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:"}, "fallback_fields": [], "source_language": "en", "original_snapshot_sha256": "6d22b942d75eef91df051c86e31121c3997a47be5740b104a71a778e658580bc"}, "evidence_kind": "source and documentation", "explain_names": ["Incremental Sort"], "partial_modes": [], "comparison_data": {"node_tag": "T_IncrementalSort", "strategies": [], "text_names": ["Incremental Sort"], "initializer": "ExecInitIncrementalSort", "partial_modes": [], "memory_mechanism": "tuplesort", "parallel_callbacks": ["ExecIncrementalSortEstimate", "ExecIncrementalSortInitializeDSM", "ExecIncrementalSortInitializeWorker", "ExecIncrementalSortRetrieveInstrumentation"]}, "comparison_hash": "28d8e33452af10dcac50fa98fa4c5c6f639be663ae15b475f003e7c287e678f4", "explain_prefixes": ["Parallel", "Async"], "runtime_verified": false, "source_inventory": {"explain": "src/backend/commands/explain.c", "executor": "src/backend/executor/execProcnode.c", "implementation": "src/backend/executor/nodeIncrementalSort.c"}, "parallel_callbacks": ["ExecIncrementalSortEstimate", "ExecIncrementalSortInitializeDSM", "ExecIncrementalSortInitializeWorker", "ExecIncrementalSortRetrieveInstrumentation"]}, "17": {"facts": [{"label": "\u6838\u5fc3\u8282\u70b9\u6807\u7b7e", "value": "T_IncrementalSort"}, {"label": "\u7ed3\u6784\u5316 EXPLAIN \u8282\u70b9\u7c7b\u578b", "value": "Incremental Sort"}, {"label": "\u8f93\u5165", "value": "\u4e00\u4e2a\u90e8\u5206\u6709\u5e8f\u7684\u5b50\u8ba1\u5212"}, {"label": "\u8f93\u51fa", "value": "\u6309\u5b8c\u6574\u6392\u5e8f\u952e\u6392\u5e8f\u7684\u5143\u7ec4"}, {"label": "\u6267\u884c\u5668\u521d\u59cb\u5316\u51fd\u6570", "value": "ExecInitIncrementalSort"}, {"label": "\u5185\u5b58\u673a\u5236", "value": "tuplesort"}], "memory": {"evidence": [{"url": "https://ftp.postgresql.org/pub/source/v17.11/postgresql-17.11.tar.bz2", "path": "src/backend/executor/nodeIncrementalSort.c", "label": "src/backend/executor/nodeIncrementalSort.c", "sha256": "e2e237d2eb6e31937d3860407906e09e5cc92cf7938ade9d79b4168aa8587d66", "archive_sha256": "dd27f2b3c59e73ed14aa3324901242bf69a032a6347805f274e6260322d42979"}, {"url": "https://ftp.postgresql.org/pub/source/v17.11/postgresql-17.11.tar.bz2", "path": "src/backend/utils/sort/tuplesort.c", "label": "src/backend/utils/sort/tuplesort.c", "sha256": "a353a6ff27e5ad56e35624ef271b557876ac7fa321ab387987ff02a745869b5e", "archive_sha256": "dd27f2b3c59e73ed14aa3324901242bf69a032a6347805f274e6260322d42979"}], "mechanism": "tuplesort", "description": "\u6b64\u8282\u70b9\u5c06 work_mem \u4f20\u7ed9 tuplesort\u3002\u6392\u5e8f\u53ef\u4f7f\u7528\u5185\u5b58\u6216\u4e34\u65f6\u6587\u4ef6\uff1b\u5b9e\u9645\u65b9\u6cd5\u548c\u7a7a\u95f4\u7528\u91cf\u53d6\u51b3\u4e8e\u8f93\u5165\u53ca\u8ba1\u5212\u3002", "source_notes": ["Incremental sort may be more efficient than plain sort, particularly on large datasets, as it reduces the amount of data to sort at once, making it more likely it fits into work_mem (eliminating the need to spill to disk). But the main advantage of incremental sort is that it can start producing rows early, before sorting the whole dataset, which is a significant benefit especially for queries with LIMIT.", "Because incremental sort processes (potentially many) sort batches, we need to capture tuplesort stats each time we finalize a sort state. This summary data is later used for EXPLAIN ANALYZE output."]}, "tables": [{"key": "explain-labels", "rows": [{"label": "Incremental Sort", "identity": "Incremental Sort"}], "title": "\u672c\u6784\u5efa\u4e2d\u7684 EXPLAIN \u6807\u7b7e", "columns": [{"key": "label", "label": "\u6587\u672c\u683c\u5f0f\u6807\u7b7e"}, {"key": "identity", "label": "\u7ed3\u6784\u5316\u8282\u70b9\u6807\u8bc6"}]}], "related": [{"url": "/wiki/sql/explain/?v=17", "label": "EXPLAIN"}, {"url": "/docs/17/using-explain.html", "label": "\u4f7f\u7528 EXPLAIN"}, {"url": "/docs/17/parallel-plans.html", "label": "\u5e76\u884c\u8ba1\u5212"}, {"url": "/wiki/guc/enable_incremental_sort/?v=17", "label": "enable_incremental_sort"}, {"url": "/wiki/guc/work_mem/?v=17", "label": "work_mem"}], "release": {"ref": "PostgreSQL 17.11 source archive", "label": "17.11", "major": "17", "channel": "stable", "revision": "dd27f2b3c59e73ed14aa3324901242bf69a032a6347805f274e6260322d42979", "source_url": "https://ftp.postgresql.org/pub/source/v17.11/postgresql-17.11.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v17.11/postgresql-17.11.tar.bz2", "line": 1540, "path": "src/backend/commands/explain.c", "label": "src/backend/commands/explain.c:1540", "sha256": "741251b1a3b6d269a52a673d42eb63b02e13a5872db7b359b137086ab21b63c8", "archive_sha256": "dd27f2b3c59e73ed14aa3324901242bf69a032a6347805f274e6260322d42979"}, {"url": "https://ftp.postgresql.org/pub/source/v17.11/postgresql-17.11.tar.bz2", "line": 325, "path": "src/backend/executor/execProcnode.c", "label": "src/backend/executor/execProcnode.c:325", "sha256": "a77576e158b94cb01fa8c5174ba133004eabdd727660323f8afc66c8d2e757b8", "archive_sha256": "dd27f2b3c59e73ed14aa3324901242bf69a032a6347805f274e6260322d42979"}, {"url": "https://ftp.postgresql.org/pub/source/v17.11/postgresql-17.11.tar.bz2", "path": "src/backend/executor/nodeIncrementalSort.c", "label": "src/backend/executor/nodeIncrementalSort.c", "sha256": "e2e237d2eb6e31937d3860407906e09e5cc92cf7938ade9d79b4168aa8587d66", "archive_sha256": "dd27f2b3c59e73ed14aa3324901242bf69a032a6347805f274e6260322d42979"}, {"url": "https://ftp.postgresql.org/pub/source/v17.11/postgresql-17.11.tar.bz2", "path": "src/include/nodes/plannodes.h", "label": "src/include/nodes/plannodes.h", "sha256": "d390dd69e2d3f5085beb42b33e46ff0676a2959b916a12b82118a7e545f8e562", "archive_sha256": "dd27f2b3c59e73ed14aa3324901242bf69a032a6347805f274e6260322d42979"}, {"url": "https://ftp.postgresql.org/pub/source/v17.11/postgresql-17.11.tar.bz2", "path": "src/backend/utils/sort/tuplesort.c", "label": "src/backend/utils/sort/tuplesort.c", "sha256": "a353a6ff27e5ad56e35624ef271b557876ac7fa321ab387987ff02a745869b5e", "archive_sha256": "dd27f2b3c59e73ed14aa3324901242bf69a032a6347805f274e6260322d42979"}, {"url": "https://pg.center/docs/17/using-explain.html#USING-EXPLAIN-BASICS", "path": "using-explain.html", "label": "PostgreSQL 17.11 \u00b7 using-explain", "sha256": "8e3422c77496cc53bfc225ccadda3e82eb23c8c362b8eb95e7fb02cdb315ea78", "language": "en", "original_url": "/docs/17/using-explain.html#USING-EXPLAIN-BASICS"}], "node_tag": "T_IncrementalSort", "sections": [{"title": "EXPLAIN \u540d\u79f0\u4e0e\u5c5e\u6027", "paragraphs": ["\u7ed3\u6784\u5316\u683c\u5f0f\u4f7f\u7528\u4e0a\u8ff0 Node Type\u3002\u6587\u672c\u683c\u5f0f\u540d\u79f0\u8fd8\u53ef\u80fd\u5305\u542b\u64cd\u4f5c\u3001\u7b56\u7565\u3001\u8fde\u63a5\u7c7b\u578b\u3001\u626b\u63cf\u65b9\u5411\u6216\u805a\u5408\u9636\u6bb5\u5c5e\u6027\u3002", "\u6b64\u6e90\u7801\u8bb0\u5f55\u7684\u6587\u672c\u540d\u79f0\uff1aIncremental Sort.", "\u5e76\u884c\u611f\u77e5\u4e0e\u5e76\u884c\u5b89\u5168\u662f\u4e0d\u540c\u7684\u8ba1\u5212\u5c5e\u6027\u3002\u5728\u5e76\u884c\u5de5\u4f5c\u8fdb\u7a0b\u5185\u8fd0\u884c\u7684\u8282\u70b9\u4e0d\u4e00\u5b9a\u662f\u5e76\u884c\u611f\u77e5\u8282\u70b9\u3002"]}, {"title": "\u5185\u5b58\u4e0e\u4e34\u65f6\u5b58\u50a8", "paragraphs": ["\u6b64\u8282\u70b9\u5c06 work_mem \u4f20\u7ed9 tuplesort\u3002\u6392\u5e8f\u53ef\u4f7f\u7528\u5185\u5b58\u6216\u4e34\u65f6\u6587\u4ef6\uff1b\u5b9e\u9645\u65b9\u6cd5\u548c\u7a7a\u95f4\u7528\u91cf\u53d6\u51b3\u4e8e\u8f93\u5165\u53ca\u8ba1\u5212\u3002", "\u589e\u91cf\u6392\u5e8f\u53ef\u80fd\u6bd4\u666e\u901a\u6392\u5e8f\u66f4\u9ad8\u6548\uff0c\u5c24\u5176\u5bf9\u4e8e\u5927\u578b\u6570\u636e\u96c6\uff0c\u56e0\u4e3a\u5b83\u51cf\u5c11\u4e86\u6bcf\u6b21\u6392\u5e8f\u7684\u6570\u636e\u91cf\uff0c\u66f4\u53ef\u80fd\u653e\u5165 work_mem\uff0c\u4ece\u800c\u907f\u514d\u843d\u76d8\u3002\u4f46\u5176\u4e3b\u8981\u4f18\u52bf\u662f\u5728\u6574\u4e2a\u6570\u636e\u96c6\u6392\u5e8f\u5b8c\u6210\u4e4b\u524d\u5c31\u80fd\u5f00\u59cb\u8f93\u51fa\u884c\uff0c\u8fd9\u5bf9\u5e26 LIMIT \u7684\u67e5\u8be2\u5c24\u5176\u6709\u5229\u3002", "\u589e\u91cf\u6392\u5e8f\u53ef\u80fd\u5904\u7406\u8bb8\u591a\u6392\u5e8f\u6279\u6b21\uff0c\u56e0\u6b64\u6bcf\u6b21\u7ed3\u675f\u4e00\u4e2a\u6392\u5e8f\u72b6\u6001\u65f6\u90fd\u8981\u8bb0\u5f55 tuplesort \u7edf\u8ba1\u4fe1\u606f\u3002\u8fd9\u4e9b\u6c47\u603b\u6570\u636e\u968f\u540e\u7528\u4e8e EXPLAIN ANALYZE \u8f93\u51fa\u3002"]}, {"title": "\u5e76\u884c\u6267\u884c\u4e0e\u8fd0\u884c\u4fe1\u606f\u91c7\u96c6", "paragraphs": ["\u4ee5\u4e0b\u6e90\u7801\u56de\u8c03\u53ef\u4ee5\u534f\u8c03\u6267\u884c\u6216\u6536\u96c6\u5de5\u4f5c\u8fdb\u7a0b\u7684\u6d4b\u91cf\u6570\u636e\u3002\u56de\u8c03\u5b58\u5728\u4e0d\u4ee3\u8868\u8be5\u8282\u70b9\u666e\u904d\u652f\u6301\u5171\u4eab\u5e76\u884c\u626b\u63cf\u6216\u5171\u4eab\u72b6\u6001\u3002", "\u6b64\u6784\u5efa\u7684\u56de\u8c03\uff1aExecIncrementalSortEstimate, ExecIncrementalSortInitializeDSM, ExecIncrementalSortInitializeWorker, ExecIncrementalSortRetrieveInstrumentation."]}, {"title": "\u540c\u7248\u672c\u624b\u518c\u8bf4\u660e", "paragraphs": ["\u5982\u679c\u8ba1\u5212\u4e2d\u7684\u67d0\u4e00\u90e8\u5206\u5df2\u7ecf\u4fdd\u8bc1\u4e86\u6240\u9700\u6392\u5e8f\u952e\u524d\u7f00\u7684\u987a\u5e8f\uff0c\u89c4\u5212\u5668\u4e5f\u53ef\u80fd\u6539\u7528 Incremental Sort \u6b65\u9aa4\uff1a"]}, {"title": "\u672c\u7248\u624b\u518c\u4e2d\u7684\u793a\u4f8b", "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   ->  Incremental Sort  (cost=19.35..2033.39 rows=10000 width=244)\n         Sort Key: hundred, ten\n         Presorted Key: hundred\n         ->  Index Scan using tenk1_hundred on tenk1  (cost=0.29..1574.20 rows=10000 width=244)", "source": {"url": "/docs/17/using-explain.html#USING-EXPLAIN-BASICS", "path": "using-explain.html", "label": "PostgreSQL 17.11 \u00b7 using-explain", "sha256": "8e3422c77496cc53bfc225ccadda3e82eb23c8c362b8eb95e7fb02cdb315ea78"}, "paragraphs": ["\u793a\u4f8b\u6458\u81ea PostgreSQL 17.11 \u624b\u518c\uff1b\u672c\u767e\u79d1\u672a\u5b9e\u9645\u6267\u884c\u6b64\u793a\u4f8b\u3002", "\u5982\u679c\u8ba1\u5212\u4e2d\u7684\u67d0\u4e00\u90e8\u5206\u5df2\u7ecf\u4fdd\u8bc1\u4e86\u6240\u9700\u6392\u5e8f\u952e\u524d\u7f00\u7684\u987a\u5e8f\uff0c\u89c4\u5212\u5668\u4e5f\u53ef\u80fd\u6539\u7528 Incremental Sort \u6b65\u9aa4\uff1a"]}]}, {"title": "\u6267\u884c\u5668\u5b9e\u73b0\u8bf4\u660e", "paragraphs": ["nodeIncrementalSort.c\uff1a\u5904\u7406\u5173\u7cfb\u589e\u91cf\u6392\u5e8f\u7684\u4f8b\u7a0b\u3002", "\u589e\u91cf\u6392\u5e8f\u662f\u591a\u952e\u6392\u5e8f\u7684\u4e00\u79cd\u4f18\u5316\u5f62\u5f0f\uff0c\u9002\u7528\u4e8e\u8f93\u5165\u5df2\u6309\u6392\u5e8f\u952e\u524d\u7f00\u6392\u597d\u5e8f\u7684\u60c5\u51b5\u3002\u4f8b\u5982\uff0c\u8981\u6c42\u6309 (key1, key2 ... keyN) \u6392\u5e8f\uff0c\u800c\u8f93\u5165\u5df2\u6309 (key1, key2 ... keyM) \u6392\u5e8f\uff0c\u4e14 M < N\uff0c\u5219\u53ef\u5c06\u8f93\u5165\u5212\u5206\u4e3a (key1, ... keyM) \u76f8\u7b49\u7684\u5206\u7ec4\uff0c\u53ea\u5bf9\u5269\u4f59\u5217\u6392\u5e8f\u3002", "\u8003\u8651\u4ee5\u4e0b\u793a\u4f8b\uff1a\u8f93\u5165\u5143\u7ec4\u7531\u4e24\u4e2a\u6574\u6570 (X, Y) \u7ec4\u6210\uff0c\u5df2\u7ecf\u6309 X \u9884\u6392\u5e8f\uff0c\u800c\u73b0\u5728\u9700\u8981\u540c\u65f6\u6309 X \u548c Y \u6392\u5e8f\u3002\u8f93\u5165\u5143\u7ec4\u5982\u4e0b\u3002", "\u589e\u91cf\u6392\u5e8f\u7b97\u6cd5\u4f1a\u6309 X \u76f8\u7b49\u5c06\u8f93\u5165\u62c6\u5206\u4e3a\u4ee5\u4e0b\u5404\u7ec4\uff0c\u518d\u5206\u522b\u6309 Y \u6392\u5e8f\uff1a", "\u5bf9\u8fd9\u4e9b\u5206\u7ec4\u5206\u522b\u6392\u5e8f\u540e\uff0c\u5c06\u5176\u62fc\u63a5\u8d77\u6765\uff0c\u5373\u53ef\u5f97\u5230\u4e0b\u9762\u6309\u8981\u6c42\u540c\u65f6\u6309 X \u548c Y \u6392\u5e8f\u7684\u7ed3\u679c\uff1a"]}, {"code": "case T_IncrementalSort:\n\t\t\tpname = sname = \"Incremental Sort\";\n\t\t\tbreak;", "title": "\u6838\u5fc3\u6e90\u7801\u4e2d\u7684 EXPLAIN \u6807\u8bc6"}], "strategies": [], "description": ["\u5bf9\u5171\u4eab\u5df2\u6709\u6392\u5e8f\u952e\u524d\u7f00\u7684\u5206\u7ec4\u5206\u522b\u6392\u5e8f\uff0c\u6269\u5c55\u8f93\u5165\u5df2\u6709\u7684\u6392\u5e8f\u987a\u5e8f\u3002"], "localization": {"status": "complete", "sources": [{"url": "/docs/17/using-explain.html", "method": "same-major semantic node", "sha256": "610ae355c419b53a5e213a8c8e2eacbf34e4fa0ac8f6d27365071bc6d3c90278", "language": "zh", "matched_nodes": ["#USING-EXPLAIN/div[7]/p[29]"]}], "language": "zh", "original_text": {"/versions/17/description/0": "Extends an existing ordering by sorting groups that share the presorted key prefix.", "/versions/17/facts/0/label": "Core node tag", "/versions/17/facts/1/label": "Structured EXPLAIN Node Type", "/versions/17/facts/2/label": "Inputs", "/versions/17/facts/2/value": "One partly ordered child plan", "/versions/17/facts/3/label": "Output", "/versions/17/facts/3/value": "Tuples ordered by the full sort key", "/versions/17/facts/4/label": "Executor initializer", "/versions/17/facts/5/label": "Memory mechanism", "/versions/17/tables/0/title": "EXPLAIN labels in this source build", "/versions/17/related/1/label": "Using EXPLAIN", "/versions/17/related/2/label": "Parallel plans", "/versions/17/sections/0/title": "EXPLAIN names and attributes", "/versions/17/sections/1/title": "Memory and temporary storage", "/versions/17/sections/2/title": "Parallel execution and instrumentation", "/versions/17/sections/3/title": "Same-version manual discussion", "/versions/17/sections/4/title": "Examples from this manual build", "/versions/17/sections/5/title": "Executor implementation notes", "/versions/17/sections/6/title": "EXPLAIN identity in core source", "/versions/17/memory/description": "The node passes work_mem to tuplesort. Sorting can use memory or temporary files; the actual method and space use depend on the input and plan.", "/versions/17/sections/0/paragraphs/0": "Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.", "/versions/17/sections/0/paragraphs/1": "Text names recorded by this source: Incremental Sort.", "/versions/17/sections/0/paragraphs/2": "Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node.", "/versions/17/sections/1/paragraphs/0": "The node passes work_mem to tuplesort. Sorting can use memory or temporary files; the actual method and space use depend on the input and plan.", "/versions/17/sections/1/paragraphs/1": "Incremental sort may be more efficient than plain sort, particularly on large datasets, as it reduces the amount of data to sort at once, making it more likely it fits into work_mem (eliminating the need to spill to disk). But the main advantage of incremental sort is that it can start producing rows early, before sorting the whole dataset, which is a significant benefit especially for queries with LIMIT.", "/versions/17/sections/1/paragraphs/2": "Because incremental sort processes (potentially many) sort batches, we need to capture tuplesort stats each time we finalize a sort state. This summary data is later used for EXPLAIN ANALYZE output.", "/versions/17/sections/2/paragraphs/0": "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.", "/versions/17/sections/2/paragraphs/1": "Callbacks in this build: ExecIncrementalSortEstimate, ExecIncrementalSortInitializeDSM, ExecIncrementalSortInitializeWorker, ExecIncrementalSortRetrieveInstrumentation.", "/versions/17/sections/3/paragraphs/0": "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:", "/versions/17/sections/5/paragraphs/0": "nodeIncrementalSort.c Routines to handle incremental sorting of relations.", "/versions/17/sections/5/paragraphs/1": "Incremental sort is an optimized variant of multikey sort for cases when the input is already sorted by a prefix of the sort keys. For example when a sort by (key1, key2 ... keyN) is requested, and the input is already sorted by (key1, key2 ... keyM), M < N, we can divide the input into groups where keys (key1, ... keyM) are equal, and only sort on the remaining columns.", "/versions/17/sections/5/paragraphs/2": "Consider the following example. We have input tuples consisting of two integers (X, Y) already presorted by X, while it's required to sort them by both X and Y. Let input tuples be following.", "/versions/17/sections/5/paragraphs/3": "An incremental sort algorithm would split the input into the following groups, which have equal X, and then sort them by Y individually:", "/versions/17/sections/5/paragraphs/4": "After sorting these groups and putting them altogether, we would get the following result which is sorted by X and Y, as requested:", "/versions/17/tables/0/columns/0/label": "Text-format label", "/versions/17/tables/0/columns/1/label": "Structured node identity", "/versions/17/sections/4/blocks/0/paragraphs/0": "Example copied from the PostgreSQL 17.11 manual; it was not executed for this collection.", "/versions/17/sections/4/blocks/0/paragraphs/1": "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:"}, "fallback_fields": [], "source_language": "en", "original_snapshot_sha256": "d4dcaf0ebe9b96fc20ec678f9af3970d1307ef9532f50fb535aa78cd35b2a8b4"}, "evidence_kind": "source and documentation", "explain_names": ["Incremental Sort"], "partial_modes": [], "comparison_data": {"node_tag": "T_IncrementalSort", "strategies": [], "text_names": ["Incremental Sort"], "initializer": "ExecInitIncrementalSort", "partial_modes": [], "memory_mechanism": "tuplesort", "parallel_callbacks": ["ExecIncrementalSortEstimate", "ExecIncrementalSortInitializeDSM", "ExecIncrementalSortInitializeWorker", "ExecIncrementalSortRetrieveInstrumentation"]}, "comparison_hash": "28d8e33452af10dcac50fa98fa4c5c6f639be663ae15b475f003e7c287e678f4", "explain_prefixes": ["Parallel", "Async"], "runtime_verified": false, "source_inventory": {"explain": "src/backend/commands/explain.c", "executor": "src/backend/executor/execProcnode.c", "implementation": "src/backend/executor/nodeIncrementalSort.c"}, "parallel_callbacks": ["ExecIncrementalSortEstimate", "ExecIncrementalSortInitializeDSM", "ExecIncrementalSortInitializeWorker", "ExecIncrementalSortRetrieveInstrumentation"]}, "18": {"facts": [{"label": "\u6838\u5fc3\u8282\u70b9\u6807\u7b7e", "value": "T_IncrementalSort"}, {"label": "\u7ed3\u6784\u5316 EXPLAIN \u8282\u70b9\u7c7b\u578b", "value": "Incremental Sort"}, {"label": "\u8f93\u5165", "value": "\u4e00\u4e2a\u90e8\u5206\u6709\u5e8f\u7684\u5b50\u8ba1\u5212"}, {"label": "\u8f93\u51fa", "value": "\u6309\u5b8c\u6574\u6392\u5e8f\u952e\u6392\u5e8f\u7684\u5143\u7ec4"}, {"label": "\u6267\u884c\u5668\u521d\u59cb\u5316\u51fd\u6570", "value": "ExecInitIncrementalSort"}, {"label": "\u5185\u5b58\u673a\u5236", "value": "tuplesort"}], "memory": {"evidence": [{"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "path": "src/backend/executor/nodeIncrementalSort.c", "label": "src/backend/executor/nodeIncrementalSort.c", "sha256": "9fd15ce79cd3dd5c131c5bfb322039213cba9232fdfaa5b53e5f40e7d17195cf", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "path": "src/backend/utils/sort/tuplesort.c", "label": "src/backend/utils/sort/tuplesort.c", "sha256": "509d4cef598613bbf0725f697e1e1e33f3dfc8debed20169a6c4bf1ac9e5c2e3", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}], "mechanism": "tuplesort", "description": "\u6b64\u8282\u70b9\u5c06 work_mem \u4f20\u7ed9 tuplesort\u3002\u6392\u5e8f\u53ef\u4f7f\u7528\u5185\u5b58\u6216\u4e34\u65f6\u6587\u4ef6\uff1b\u5b9e\u9645\u65b9\u6cd5\u548c\u7a7a\u95f4\u7528\u91cf\u53d6\u51b3\u4e8e\u8f93\u5165\u53ca\u8ba1\u5212\u3002", "source_notes": ["Incremental sort may be more efficient than plain sort, particularly on large datasets, as it reduces the amount of data to sort at once, making it more likely it fits into work_mem (eliminating the need to spill to disk). But the main advantage of incremental sort is that it can start producing rows early, before sorting the whole dataset, which is a significant benefit especially for queries with LIMIT.", "Because incremental sort processes (potentially many) sort batches, we need to capture tuplesort stats each time we finalize a sort state. This summary data is later used for EXPLAIN ANALYZE output."]}, "tables": [{"key": "explain-labels", "rows": [{"label": "Incremental Sort", "identity": "Incremental Sort"}], "title": "\u672c\u6784\u5efa\u4e2d\u7684 EXPLAIN \u6807\u7b7e", "columns": [{"key": "label", "label": "\u6587\u672c\u683c\u5f0f\u6807\u7b7e"}, {"key": "identity", "label": "\u7ed3\u6784\u5316\u8282\u70b9\u6807\u8bc6"}]}], "related": [{"url": "/wiki/sql/explain/?v=18", "label": "EXPLAIN"}, {"url": "/docs/18/using-explain.html", "label": "\u4f7f\u7528 EXPLAIN"}, {"url": "/docs/18/parallel-plans.html", "label": "\u5e76\u884c\u8ba1\u5212"}, {"url": "/wiki/guc/enable_incremental_sort/?v=18", "label": "enable_incremental_sort"}, {"url": "/wiki/guc/work_mem/?v=18", "label": "work_mem"}], "release": {"ref": "PostgreSQL 18.6 source archive", "label": "18.6", "major": "18", "channel": "stable", "revision": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f", "source_url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "line": 1525, "path": "src/backend/commands/explain.c", "label": "src/backend/commands/explain.c:1525", "sha256": "34c86d6070224a0e981efef51f79101d6d505e5874f1684ace183034bab14bb4", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "line": 325, "path": "src/backend/executor/execProcnode.c", "label": "src/backend/executor/execProcnode.c:325", "sha256": "f8a06a3f539077249b20664b2812433db6d7bd12b2c0ca633525db43d06f112a", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "path": "src/backend/executor/nodeIncrementalSort.c", "label": "src/backend/executor/nodeIncrementalSort.c", "sha256": "9fd15ce79cd3dd5c131c5bfb322039213cba9232fdfaa5b53e5f40e7d17195cf", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "path": "src/include/nodes/plannodes.h", "label": "src/include/nodes/plannodes.h", "sha256": "52422b327a8049fbbb20d8b96008a0fc0a6fafa60f7eff3c695d5b2e83830120", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "path": "src/backend/utils/sort/tuplesort.c", "label": "src/backend/utils/sort/tuplesort.c", "sha256": "509d4cef598613bbf0725f697e1e1e33f3dfc8debed20169a6c4bf1ac9e5c2e3", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "https://pg.center/docs/18/using-explain.html#USING-EXPLAIN-BASICS", "path": "using-explain.html", "label": "PostgreSQL 18.6 \u00b7 using-explain", "sha256": "60040c30180093418a0affe56dd27dff9df2504b705b38039589e458bf5c31ed", "language": "en", "original_url": "/docs/18/using-explain.html#USING-EXPLAIN-BASICS"}], "node_tag": "T_IncrementalSort", "sections": [{"title": "EXPLAIN \u540d\u79f0\u4e0e\u5c5e\u6027", "paragraphs": ["\u7ed3\u6784\u5316\u683c\u5f0f\u4f7f\u7528\u4e0a\u8ff0 Node Type\u3002\u6587\u672c\u683c\u5f0f\u540d\u79f0\u8fd8\u53ef\u80fd\u5305\u542b\u64cd\u4f5c\u3001\u7b56\u7565\u3001\u8fde\u63a5\u7c7b\u578b\u3001\u626b\u63cf\u65b9\u5411\u6216\u805a\u5408\u9636\u6bb5\u5c5e\u6027\u3002", "\u6b64\u6e90\u7801\u8bb0\u5f55\u7684\u6587\u672c\u540d\u79f0\uff1aIncremental Sort.", "\u5e76\u884c\u611f\u77e5\u4e0e\u5e76\u884c\u5b89\u5168\u662f\u4e0d\u540c\u7684\u8ba1\u5212\u5c5e\u6027\u3002\u5728\u5e76\u884c\u5de5\u4f5c\u8fdb\u7a0b\u5185\u8fd0\u884c\u7684\u8282\u70b9\u4e0d\u4e00\u5b9a\u662f\u5e76\u884c\u611f\u77e5\u8282\u70b9\u3002"]}, {"title": "\u5185\u5b58\u4e0e\u4e34\u65f6\u5b58\u50a8", "paragraphs": ["\u6b64\u8282\u70b9\u5c06 work_mem \u4f20\u7ed9 tuplesort\u3002\u6392\u5e8f\u53ef\u4f7f\u7528\u5185\u5b58\u6216\u4e34\u65f6\u6587\u4ef6\uff1b\u5b9e\u9645\u65b9\u6cd5\u548c\u7a7a\u95f4\u7528\u91cf\u53d6\u51b3\u4e8e\u8f93\u5165\u53ca\u8ba1\u5212\u3002", "\u589e\u91cf\u6392\u5e8f\u53ef\u80fd\u6bd4\u666e\u901a\u6392\u5e8f\u66f4\u9ad8\u6548\uff0c\u5c24\u5176\u5bf9\u4e8e\u5927\u578b\u6570\u636e\u96c6\uff0c\u56e0\u4e3a\u5b83\u51cf\u5c11\u4e86\u6bcf\u6b21\u6392\u5e8f\u7684\u6570\u636e\u91cf\uff0c\u66f4\u53ef\u80fd\u653e\u5165 work_mem\uff0c\u4ece\u800c\u907f\u514d\u843d\u76d8\u3002\u4f46\u5176\u4e3b\u8981\u4f18\u52bf\u662f\u5728\u6574\u4e2a\u6570\u636e\u96c6\u6392\u5e8f\u5b8c\u6210\u4e4b\u524d\u5c31\u80fd\u5f00\u59cb\u8f93\u51fa\u884c\uff0c\u8fd9\u5bf9\u5e26 LIMIT \u7684\u67e5\u8be2\u5c24\u5176\u6709\u5229\u3002", "\u589e\u91cf\u6392\u5e8f\u53ef\u80fd\u5904\u7406\u8bb8\u591a\u6392\u5e8f\u6279\u6b21\uff0c\u56e0\u6b64\u6bcf\u6b21\u7ed3\u675f\u4e00\u4e2a\u6392\u5e8f\u72b6\u6001\u65f6\u90fd\u8981\u8bb0\u5f55 tuplesort \u7edf\u8ba1\u4fe1\u606f\u3002\u8fd9\u4e9b\u6c47\u603b\u6570\u636e\u968f\u540e\u7528\u4e8e EXPLAIN ANALYZE \u8f93\u51fa\u3002"]}, {"title": "\u5e76\u884c\u6267\u884c\u4e0e\u8fd0\u884c\u4fe1\u606f\u91c7\u96c6", "paragraphs": ["\u4ee5\u4e0b\u6e90\u7801\u56de\u8c03\u53ef\u4ee5\u534f\u8c03\u6267\u884c\u6216\u6536\u96c6\u5de5\u4f5c\u8fdb\u7a0b\u7684\u6d4b\u91cf\u6570\u636e\u3002\u56de\u8c03\u5b58\u5728\u4e0d\u4ee3\u8868\u8be5\u8282\u70b9\u666e\u904d\u652f\u6301\u5171\u4eab\u5e76\u884c\u626b\u63cf\u6216\u5171\u4eab\u72b6\u6001\u3002", "\u6b64\u6784\u5efa\u7684\u56de\u8c03\uff1aExecIncrementalSortEstimate, ExecIncrementalSortInitializeDSM, ExecIncrementalSortInitializeWorker, ExecIncrementalSortRetrieveInstrumentation."]}, {"title": "\u540c\u7248\u672c\u624b\u518c\u8bf4\u660e", "paragraphs": ["\u5982\u679c\u8ba1\u5212\u4e2d\u7684\u67d0\u4e00\u90e8\u5206\u5df2\u7ecf\u4fdd\u8bc1\u4e86\u6240\u9700\u6392\u5e8f\u952e\u524d\u7f00\u7684\u987a\u5e8f\uff0c\u89c4\u5212\u5668\u4e5f\u53ef\u80fd\u6539\u7528 Incremental Sort \u6b65\u9aa4\uff1a"]}, {"title": "\u672c\u7248\u624b\u518c\u4e2d\u7684\u793a\u4f8b", "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   ->  Incremental Sort  (cost=19.35..2033.39 rows=10000 width=244)\n         Sort Key: hundred, ten\n         Presorted Key: hundred\n         ->  Index Scan using tenk1_hundred on tenk1  (cost=0.29..1574.20 rows=10000 width=244)", "source": {"url": "/docs/18/using-explain.html#USING-EXPLAIN-BASICS", "path": "using-explain.html", "label": "PostgreSQL 18.6 \u00b7 using-explain", "sha256": "60040c30180093418a0affe56dd27dff9df2504b705b38039589e458bf5c31ed"}, "paragraphs": ["\u793a\u4f8b\u6458\u81ea PostgreSQL 18.6 \u624b\u518c\uff1b\u672c\u767e\u79d1\u672a\u5b9e\u9645\u6267\u884c\u6b64\u793a\u4f8b\u3002", "\u5982\u679c\u8ba1\u5212\u4e2d\u7684\u67d0\u4e00\u90e8\u5206\u5df2\u7ecf\u4fdd\u8bc1\u4e86\u6240\u9700\u6392\u5e8f\u952e\u524d\u7f00\u7684\u987a\u5e8f\uff0c\u89c4\u5212\u5668\u4e5f\u53ef\u80fd\u6539\u7528 Incremental Sort \u6b65\u9aa4\uff1a"]}]}, {"title": "\u6267\u884c\u5668\u5b9e\u73b0\u8bf4\u660e", "paragraphs": ["nodeIncrementalSort.c\uff1a\u5904\u7406\u5173\u7cfb\u589e\u91cf\u6392\u5e8f\u7684\u4f8b\u7a0b\u3002", "\u589e\u91cf\u6392\u5e8f\u662f\u591a\u952e\u6392\u5e8f\u7684\u4e00\u79cd\u4f18\u5316\u5f62\u5f0f\uff0c\u9002\u7528\u4e8e\u8f93\u5165\u5df2\u6309\u6392\u5e8f\u952e\u524d\u7f00\u6392\u597d\u5e8f\u7684\u60c5\u51b5\u3002\u4f8b\u5982\uff0c\u8981\u6c42\u6309 (key1, key2 ... keyN) \u6392\u5e8f\uff0c\u800c\u8f93\u5165\u5df2\u6309 (key1, key2 ... keyM) \u6392\u5e8f\uff0c\u4e14 M < N\uff0c\u5219\u53ef\u5c06\u8f93\u5165\u5212\u5206\u4e3a (key1, ... keyM) \u76f8\u7b49\u7684\u5206\u7ec4\uff0c\u53ea\u5bf9\u5269\u4f59\u5217\u6392\u5e8f\u3002", "\u8003\u8651\u4ee5\u4e0b\u793a\u4f8b\uff1a\u8f93\u5165\u5143\u7ec4\u7531\u4e24\u4e2a\u6574\u6570 (X, Y) \u7ec4\u6210\uff0c\u5df2\u7ecf\u6309 X \u9884\u6392\u5e8f\uff0c\u800c\u73b0\u5728\u9700\u8981\u540c\u65f6\u6309 X \u548c Y \u6392\u5e8f\u3002\u8f93\u5165\u5143\u7ec4\u5982\u4e0b\u3002", "\u589e\u91cf\u6392\u5e8f\u7b97\u6cd5\u4f1a\u6309 X \u76f8\u7b49\u5c06\u8f93\u5165\u62c6\u5206\u4e3a\u4ee5\u4e0b\u5404\u7ec4\uff0c\u518d\u5206\u522b\u6309 Y \u6392\u5e8f\uff1a", "\u5bf9\u8fd9\u4e9b\u5206\u7ec4\u5206\u522b\u6392\u5e8f\u540e\uff0c\u5c06\u5176\u62fc\u63a5\u8d77\u6765\uff0c\u5373\u53ef\u5f97\u5230\u4e0b\u9762\u6309\u8981\u6c42\u540c\u65f6\u6309 X \u548c Y \u6392\u5e8f\u7684\u7ed3\u679c\uff1a"]}, {"code": "case T_IncrementalSort:\n\t\t\tpname = sname = \"Incremental Sort\";\n\t\t\tbreak;", "title": "\u6838\u5fc3\u6e90\u7801\u4e2d\u7684 EXPLAIN \u6807\u8bc6"}], "strategies": [], "description": ["\u5bf9\u5171\u4eab\u5df2\u6709\u6392\u5e8f\u952e\u524d\u7f00\u7684\u5206\u7ec4\u5206\u522b\u6392\u5e8f\uff0c\u6269\u5c55\u8f93\u5165\u5df2\u6709\u7684\u6392\u5e8f\u987a\u5e8f\u3002"], "localization": {"status": "complete", "sources": [{"url": "/docs/18/using-explain.html", "method": "same-major semantic node", "sha256": "b8835ec9adbc70ec150667a6b5443f8d298222dc0cc8c2bd1abb1c1d64895904", "language": "zh", "matched_nodes": ["#USING-EXPLAIN/div[7]/p[29]"]}], "language": "zh", "original_text": {"/versions/18/description/0": "Extends an existing ordering by sorting groups that share the presorted key prefix.", "/versions/18/facts/0/label": "Core node tag", "/versions/18/facts/1/label": "Structured EXPLAIN Node Type", "/versions/18/facts/2/label": "Inputs", "/versions/18/facts/2/value": "One partly ordered child plan", "/versions/18/facts/3/label": "Output", "/versions/18/facts/3/value": "Tuples ordered by the full sort key", "/versions/18/facts/4/label": "Executor initializer", "/versions/18/facts/5/label": "Memory mechanism", "/versions/18/tables/0/title": "EXPLAIN labels in this source build", "/versions/18/related/1/label": "Using EXPLAIN", "/versions/18/related/2/label": "Parallel plans", "/versions/18/sections/0/title": "EXPLAIN names and attributes", "/versions/18/sections/1/title": "Memory and temporary storage", "/versions/18/sections/2/title": "Parallel execution and instrumentation", "/versions/18/sections/3/title": "Same-version manual discussion", "/versions/18/sections/4/title": "Examples from this manual build", "/versions/18/sections/5/title": "Executor implementation notes", "/versions/18/sections/6/title": "EXPLAIN identity in core source", "/versions/18/memory/description": "The node passes work_mem to tuplesort. Sorting can use memory or temporary files; the actual method and space use depend on the input and plan.", "/versions/18/sections/0/paragraphs/0": "Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.", "/versions/18/sections/0/paragraphs/1": "Text names recorded by this source: Incremental Sort.", "/versions/18/sections/0/paragraphs/2": "Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node.", "/versions/18/sections/1/paragraphs/0": "The node passes work_mem to tuplesort. Sorting can use memory or temporary files; the actual method and space use depend on the input and plan.", "/versions/18/sections/1/paragraphs/1": "Incremental sort may be more efficient than plain sort, particularly on large datasets, as it reduces the amount of data to sort at once, making it more likely it fits into work_mem (eliminating the need to spill to disk). But the main advantage of incremental sort is that it can start producing rows early, before sorting the whole dataset, which is a significant benefit especially for queries with LIMIT.", "/versions/18/sections/1/paragraphs/2": "Because incremental sort processes (potentially many) sort batches, we need to capture tuplesort stats each time we finalize a sort state. This summary data is later used for EXPLAIN ANALYZE output.", "/versions/18/sections/2/paragraphs/0": "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.", "/versions/18/sections/2/paragraphs/1": "Callbacks in this build: ExecIncrementalSortEstimate, ExecIncrementalSortInitializeDSM, ExecIncrementalSortInitializeWorker, ExecIncrementalSortRetrieveInstrumentation.", "/versions/18/sections/3/paragraphs/0": "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:", "/versions/18/sections/5/paragraphs/0": "nodeIncrementalSort.c Routines to handle incremental sorting of relations.", "/versions/18/sections/5/paragraphs/1": "Incremental sort is an optimized variant of multikey sort for cases when the input is already sorted by a prefix of the sort keys. For example when a sort by (key1, key2 ... keyN) is requested, and the input is already sorted by (key1, key2 ... keyM), M < N, we can divide the input into groups where keys (key1, ... keyM) are equal, and only sort on the remaining columns.", "/versions/18/sections/5/paragraphs/2": "Consider the following example. We have input tuples consisting of two integers (X, Y) already presorted by X, while it's required to sort them by both X and Y. Let input tuples be following.", "/versions/18/sections/5/paragraphs/3": "An incremental sort algorithm would split the input into the following groups, which have equal X, and then sort them by Y individually:", "/versions/18/sections/5/paragraphs/4": "After sorting these groups and putting them altogether, we would get the following result which is sorted by X and Y, as requested:", "/versions/18/tables/0/columns/0/label": "Text-format label", "/versions/18/tables/0/columns/1/label": "Structured node identity", "/versions/18/sections/4/blocks/0/paragraphs/0": "Example copied from the PostgreSQL 18.6 manual; it was not executed for this collection.", "/versions/18/sections/4/blocks/0/paragraphs/1": "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:"}, "fallback_fields": [], "source_language": "en", "original_snapshot_sha256": "e3f6e08bd43d692c547cef700107fe9837e03dd63bf94eb96065dfdba77e7446"}, "evidence_kind": "source and documentation", "explain_names": ["Incremental Sort"], "partial_modes": [], "comparison_data": {"node_tag": "T_IncrementalSort", "strategies": [], "text_names": ["Incremental Sort"], "initializer": "ExecInitIncrementalSort", "partial_modes": [], "memory_mechanism": "tuplesort", "parallel_callbacks": ["ExecIncrementalSortEstimate", "ExecIncrementalSortInitializeDSM", "ExecIncrementalSortInitializeWorker", "ExecIncrementalSortRetrieveInstrumentation"]}, "comparison_hash": "28d8e33452af10dcac50fa98fa4c5c6f639be663ae15b475f003e7c287e678f4", "explain_prefixes": ["Parallel", "Async"], "runtime_verified": false, "source_inventory": {"explain": "src/backend/commands/explain.c", "executor": "src/backend/executor/execProcnode.c", "implementation": "src/backend/executor/nodeIncrementalSort.c"}, "parallel_callbacks": ["ExecIncrementalSortEstimate", "ExecIncrementalSortInitializeDSM", "ExecIncrementalSortInitializeWorker", "ExecIncrementalSortRetrieveInstrumentation"]}, "19": {"facts": [{"label": "\u6838\u5fc3\u8282\u70b9\u6807\u7b7e", "value": "T_IncrementalSort"}, {"label": "\u7ed3\u6784\u5316 EXPLAIN \u8282\u70b9\u7c7b\u578b", "value": "Incremental Sort"}, {"label": "\u8f93\u5165", "value": "\u4e00\u4e2a\u90e8\u5206\u6709\u5e8f\u7684\u5b50\u8ba1\u5212"}, {"label": "\u8f93\u51fa", "value": "\u6309\u5b8c\u6574\u6392\u5e8f\u952e\u6392\u5e8f\u7684\u5143\u7ec4"}, {"label": "\u6267\u884c\u5668\u521d\u59cb\u5316\u51fd\u6570", "value": "ExecInitIncrementalSort"}, {"label": "\u5185\u5b58\u673a\u5236", "value": "tuplesort"}], "memory": {"evidence": [{"url": "https://ftp.postgresql.org/pub/source/v19beta4/postgresql-19beta4.tar.bz2", "path": "src/backend/executor/nodeIncrementalSort.c", "label": "src/backend/executor/nodeIncrementalSort.c", "sha256": "db15e8bf76c94eb736daa76b82937cf6d194aee9e2337dad4752d8babc65ee85", "archive_sha256": "83157ee9c599d03b2f7a3d73ef3a56ec24e0e79cc2b3501a64d1364f56398c86"}, {"url": "https://ftp.postgresql.org/pub/source/v19beta4/postgresql-19beta4.tar.bz2", "path": "src/backend/utils/sort/tuplesort.c", "label": "src/backend/utils/sort/tuplesort.c", "sha256": "5687562c1a9a65e8b567ec865e0cb04e0cd6b3e196dbf13afdde7d52c4eb16ae", "archive_sha256": "83157ee9c599d03b2f7a3d73ef3a56ec24e0e79cc2b3501a64d1364f56398c86"}], "mechanism": "tuplesort", "description": "\u6b64\u8282\u70b9\u5c06 work_mem \u4f20\u7ed9 tuplesort\u3002\u6392\u5e8f\u53ef\u4f7f\u7528\u5185\u5b58\u6216\u4e34\u65f6\u6587\u4ef6\uff1b\u5b9e\u9645\u65b9\u6cd5\u548c\u7a7a\u95f4\u7528\u91cf\u53d6\u51b3\u4e8e\u8f93\u5165\u53ca\u8ba1\u5212\u3002", "source_notes": ["Incremental sort may be more efficient than plain sort, particularly on large datasets, as it reduces the amount of data to sort at once, making it more likely it fits into work_mem (eliminating the need to spill to disk). But the main advantage of incremental sort is that it can start producing rows early, before sorting the whole dataset, which is a significant benefit especially for queries with LIMIT.", "Because incremental sort processes (potentially many) sort batches, we need to capture tuplesort stats each time we finalize a sort state. This summary data is later used for EXPLAIN ANALYZE output."]}, "tables": [{"key": "explain-labels", "rows": [{"label": "Incremental Sort", "identity": "Incremental Sort"}], "title": "\u672c\u6784\u5efa\u4e2d\u7684 EXPLAIN \u6807\u7b7e", "columns": [{"key": "label", "label": "\u6587\u672c\u683c\u5f0f\u6807\u7b7e"}, {"key": "identity", "label": "\u7ed3\u6784\u5316\u8282\u70b9\u6807\u8bc6"}]}], "related": [{"url": "/wiki/sql/explain/?v=19", "label": "EXPLAIN"}, {"url": "/docs/19/using-explain.html", "label": "\u4f7f\u7528 EXPLAIN"}, {"url": "/docs/19/parallel-plans.html", "label": "\u5e76\u884c\u8ba1\u5212"}, {"url": "/wiki/guc/enable_incremental_sort/?v=19", "label": "enable_incremental_sort"}, {"url": "/wiki/guc/work_mem/?v=19", "label": "work_mem"}], "release": {"ref": "PostgreSQL 19beta4 source archive", "label": "19beta4", "major": "19", "channel": "preview", "revision": "83157ee9c599d03b2f7a3d73ef3a56ec24e0e79cc2b3501a64d1364f56398c86", "source_url": "https://ftp.postgresql.org/pub/source/v19beta4/postgresql-19beta4.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v19beta4/postgresql-19beta4.tar.bz2", "line": 1537, "path": "src/backend/commands/explain.c", "label": "src/backend/commands/explain.c:1537", "sha256": "8b115b1c194a4b54ae630209a741e293b1df49a9052f10b2de9ca092a48998e3", "archive_sha256": "83157ee9c599d03b2f7a3d73ef3a56ec24e0e79cc2b3501a64d1364f56398c86"}, {"url": "https://ftp.postgresql.org/pub/source/v19beta4/postgresql-19beta4.tar.bz2", "line": 325, "path": "src/backend/executor/execProcnode.c", "label": "src/backend/executor/execProcnode.c:325", "sha256": "5e39b2037bed672da55104229ecc32da5abde44c26bcad01479edcfa044d09ed", "archive_sha256": "83157ee9c599d03b2f7a3d73ef3a56ec24e0e79cc2b3501a64d1364f56398c86"}, {"url": "https://ftp.postgresql.org/pub/source/v19beta4/postgresql-19beta4.tar.bz2", "path": "src/backend/executor/nodeIncrementalSort.c", "label": "src/backend/executor/nodeIncrementalSort.c", "sha256": "db15e8bf76c94eb736daa76b82937cf6d194aee9e2337dad4752d8babc65ee85", "archive_sha256": "83157ee9c599d03b2f7a3d73ef3a56ec24e0e79cc2b3501a64d1364f56398c86"}, {"url": "https://ftp.postgresql.org/pub/source/v19beta4/postgresql-19beta4.tar.bz2", "path": "src/include/nodes/plannodes.h", "label": "src/include/nodes/plannodes.h", "sha256": "1c65d5d6b6c81c71531685843647869bcae630779d815a5036b06e070c6c06c7", "archive_sha256": "83157ee9c599d03b2f7a3d73ef3a56ec24e0e79cc2b3501a64d1364f56398c86"}, {"url": "https://ftp.postgresql.org/pub/source/v19beta4/postgresql-19beta4.tar.bz2", "path": "src/backend/utils/sort/tuplesort.c", "label": "src/backend/utils/sort/tuplesort.c", "sha256": "5687562c1a9a65e8b567ec865e0cb04e0cd6b3e196dbf13afdde7d52c4eb16ae", "archive_sha256": "83157ee9c599d03b2f7a3d73ef3a56ec24e0e79cc2b3501a64d1364f56398c86"}, {"url": "https://pg.center/docs/19/using-explain.html#USING-EXPLAIN-BASICS", "path": "using-explain.html", "label": "PostgreSQL 19beta4 \u00b7 using-explain", "sha256": "52f111fbd213e2200146319d01a9dcc2ea90001617d2a28edc52f7954c2dd70b", "language": "en", "original_url": "/docs/19/using-explain.html#USING-EXPLAIN-BASICS"}], "node_tag": "T_IncrementalSort", "sections": [{"title": "EXPLAIN \u540d\u79f0\u4e0e\u5c5e\u6027", "paragraphs": ["\u7ed3\u6784\u5316\u683c\u5f0f\u4f7f\u7528\u4e0a\u8ff0 Node Type\u3002\u6587\u672c\u683c\u5f0f\u540d\u79f0\u8fd8\u53ef\u80fd\u5305\u542b\u64cd\u4f5c\u3001\u7b56\u7565\u3001\u8fde\u63a5\u7c7b\u578b\u3001\u626b\u63cf\u65b9\u5411\u6216\u805a\u5408\u9636\u6bb5\u5c5e\u6027\u3002", "\u6b64\u6e90\u7801\u8bb0\u5f55\u7684\u6587\u672c\u540d\u79f0\uff1aIncremental Sort.", "\u5e76\u884c\u611f\u77e5\u4e0e\u5e76\u884c\u5b89\u5168\u662f\u4e0d\u540c\u7684\u8ba1\u5212\u5c5e\u6027\u3002\u5728\u5e76\u884c\u5de5\u4f5c\u8fdb\u7a0b\u5185\u8fd0\u884c\u7684\u8282\u70b9\u4e0d\u4e00\u5b9a\u662f\u5e76\u884c\u611f\u77e5\u8282\u70b9\u3002"]}, {"title": "\u5185\u5b58\u4e0e\u4e34\u65f6\u5b58\u50a8", "paragraphs": ["\u6b64\u8282\u70b9\u5c06 work_mem \u4f20\u7ed9 tuplesort\u3002\u6392\u5e8f\u53ef\u4f7f\u7528\u5185\u5b58\u6216\u4e34\u65f6\u6587\u4ef6\uff1b\u5b9e\u9645\u65b9\u6cd5\u548c\u7a7a\u95f4\u7528\u91cf\u53d6\u51b3\u4e8e\u8f93\u5165\u53ca\u8ba1\u5212\u3002", "\u589e\u91cf\u6392\u5e8f\u53ef\u80fd\u6bd4\u666e\u901a\u6392\u5e8f\u66f4\u9ad8\u6548\uff0c\u5c24\u5176\u5bf9\u4e8e\u5927\u578b\u6570\u636e\u96c6\uff0c\u56e0\u4e3a\u5b83\u51cf\u5c11\u4e86\u6bcf\u6b21\u6392\u5e8f\u7684\u6570\u636e\u91cf\uff0c\u66f4\u53ef\u80fd\u653e\u5165 work_mem\uff0c\u4ece\u800c\u907f\u514d\u843d\u76d8\u3002\u4f46\u5176\u4e3b\u8981\u4f18\u52bf\u662f\u5728\u6574\u4e2a\u6570\u636e\u96c6\u6392\u5e8f\u5b8c\u6210\u4e4b\u524d\u5c31\u80fd\u5f00\u59cb\u8f93\u51fa\u884c\uff0c\u8fd9\u5bf9\u5e26 LIMIT \u7684\u67e5\u8be2\u5c24\u5176\u6709\u5229\u3002", "\u589e\u91cf\u6392\u5e8f\u53ef\u80fd\u5904\u7406\u8bb8\u591a\u6392\u5e8f\u6279\u6b21\uff0c\u56e0\u6b64\u6bcf\u6b21\u7ed3\u675f\u4e00\u4e2a\u6392\u5e8f\u72b6\u6001\u65f6\u90fd\u8981\u8bb0\u5f55 tuplesort \u7edf\u8ba1\u4fe1\u606f\u3002\u8fd9\u4e9b\u6c47\u603b\u6570\u636e\u968f\u540e\u7528\u4e8e EXPLAIN ANALYZE \u8f93\u51fa\u3002"]}, {"title": "\u5e76\u884c\u6267\u884c\u4e0e\u8fd0\u884c\u4fe1\u606f\u91c7\u96c6", "paragraphs": ["\u4ee5\u4e0b\u6e90\u7801\u56de\u8c03\u53ef\u4ee5\u534f\u8c03\u6267\u884c\u6216\u6536\u96c6\u5de5\u4f5c\u8fdb\u7a0b\u7684\u6d4b\u91cf\u6570\u636e\u3002\u56de\u8c03\u5b58\u5728\u4e0d\u4ee3\u8868\u8be5\u8282\u70b9\u666e\u904d\u652f\u6301\u5171\u4eab\u5e76\u884c\u626b\u63cf\u6216\u5171\u4eab\u72b6\u6001\u3002", "\u6b64\u6784\u5efa\u7684\u56de\u8c03\uff1aExecIncrementalSortEstimate, ExecIncrementalSortInitializeDSM, ExecIncrementalSortInitializeWorker, ExecIncrementalSortRetrieveInstrumentation."]}, {"title": "\u540c\u7248\u672c\u624b\u518c\u8bf4\u660e", "paragraphs": ["\u5982\u679c\u8ba1\u5212\u4e2d\u7684\u67d0\u4e00\u90e8\u5206\u5df2\u7ecf\u4fdd\u8bc1\u4e86\u6240\u9700\u6392\u5e8f\u952e\u524d\u7f00\u7684\u987a\u5e8f\uff0c\u89c4\u5212\u5668\u4e5f\u53ef\u80fd\u6539\u7528 Incremental Sort \u6b65\u9aa4\uff1a"]}, {"title": "\u672c\u7248\u624b\u518c\u4e2d\u7684\u793a\u4f8b", "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   ->  Incremental Sort  (cost=19.35..2033.39 rows=10000 width=244)\n         Sort Key: hundred, ten\n         Presorted Key: hundred\n         ->  Index Scan using tenk1_hundred on tenk1  (cost=0.29..1574.20 rows=10000 width=244)", "source": {"url": "/docs/19/using-explain.html#USING-EXPLAIN-BASICS", "path": "using-explain.html", "label": "PostgreSQL 19beta4 \u00b7 using-explain", "sha256": "52f111fbd213e2200146319d01a9dcc2ea90001617d2a28edc52f7954c2dd70b"}, "paragraphs": ["\u793a\u4f8b\u6458\u81ea PostgreSQL 19beta4 \u624b\u518c\uff1b\u672c\u767e\u79d1\u672a\u5b9e\u9645\u6267\u884c\u6b64\u793a\u4f8b\u3002", "\u5982\u679c\u8ba1\u5212\u4e2d\u7684\u67d0\u4e00\u90e8\u5206\u5df2\u7ecf\u4fdd\u8bc1\u4e86\u6240\u9700\u6392\u5e8f\u952e\u524d\u7f00\u7684\u987a\u5e8f\uff0c\u89c4\u5212\u5668\u4e5f\u53ef\u80fd\u6539\u7528 Incremental Sort \u6b65\u9aa4\uff1a"]}]}, {"title": "\u6267\u884c\u5668\u5b9e\u73b0\u8bf4\u660e", "paragraphs": ["nodeIncrementalSort.c\uff1a\u5904\u7406\u5173\u7cfb\u589e\u91cf\u6392\u5e8f\u7684\u4f8b\u7a0b\u3002", "\u589e\u91cf\u6392\u5e8f\u662f\u591a\u952e\u6392\u5e8f\u7684\u4e00\u79cd\u4f18\u5316\u5f62\u5f0f\uff0c\u9002\u7528\u4e8e\u8f93\u5165\u5df2\u6309\u6392\u5e8f\u952e\u524d\u7f00\u6392\u597d\u5e8f\u7684\u60c5\u51b5\u3002\u4f8b\u5982\uff0c\u8981\u6c42\u6309 (key1, key2 ... keyN) \u6392\u5e8f\uff0c\u800c\u8f93\u5165\u5df2\u6309 (key1, key2 ... keyM) \u6392\u5e8f\uff0c\u4e14 M < N\uff0c\u5219\u53ef\u5c06\u8f93\u5165\u5212\u5206\u4e3a (key1, ... keyM) \u76f8\u7b49\u7684\u5206\u7ec4\uff0c\u53ea\u5bf9\u5269\u4f59\u5217\u6392\u5e8f\u3002", "\u8003\u8651\u4ee5\u4e0b\u793a\u4f8b\uff1a\u8f93\u5165\u5143\u7ec4\u7531\u4e24\u4e2a\u6574\u6570 (X, Y) \u7ec4\u6210\uff0c\u5df2\u7ecf\u6309 X \u9884\u6392\u5e8f\uff0c\u800c\u73b0\u5728\u9700\u8981\u540c\u65f6\u6309 X \u548c Y \u6392\u5e8f\u3002\u8f93\u5165\u5143\u7ec4\u5982\u4e0b\u3002", "\u589e\u91cf\u6392\u5e8f\u7b97\u6cd5\u4f1a\u6309 X \u76f8\u7b49\u5c06\u8f93\u5165\u62c6\u5206\u4e3a\u4ee5\u4e0b\u5404\u7ec4\uff0c\u518d\u5206\u522b\u6309 Y \u6392\u5e8f\uff1a", "\u5bf9\u8fd9\u4e9b\u5206\u7ec4\u5206\u522b\u6392\u5e8f\u540e\uff0c\u5c06\u5176\u62fc\u63a5\u8d77\u6765\uff0c\u5373\u53ef\u5f97\u5230\u4e0b\u9762\u6309\u8981\u6c42\u540c\u65f6\u6309 X \u548c Y \u6392\u5e8f\u7684\u7ed3\u679c\uff1a"]}, {"code": "case T_IncrementalSort:\n\t\t\tpname = sname = \"Incremental Sort\";\n\t\t\tbreak;", "title": "\u6838\u5fc3\u6e90\u7801\u4e2d\u7684 EXPLAIN \u6807\u8bc6"}], "strategies": [], "description": ["\u5bf9\u5171\u4eab\u5df2\u6709\u6392\u5e8f\u952e\u524d\u7f00\u7684\u5206\u7ec4\u5206\u522b\u6392\u5e8f\uff0c\u6269\u5c55\u8f93\u5165\u5df2\u6709\u7684\u6392\u5e8f\u987a\u5e8f\u3002"], "localization": {"status": "complete", "sources": [{"url": "/docs/19/using-explain.html", "method": "same-major semantic node", "sha256": "7cc78f59bf29afb1811ece53e9d5c572a3f634d66d7422fb8761f19bc6811492", "language": "zh", "matched_nodes": ["#USING-EXPLAIN/div[7]/p[29]"]}], "language": "zh", "original_text": {"/versions/19/description/0": "Extends an existing ordering by sorting groups that share the presorted key prefix.", "/versions/19/facts/0/label": "Core node tag", "/versions/19/facts/1/label": "Structured EXPLAIN Node Type", "/versions/19/facts/2/label": "Inputs", "/versions/19/facts/2/value": "One partly ordered child plan", "/versions/19/facts/3/label": "Output", "/versions/19/facts/3/value": "Tuples ordered by the full sort key", "/versions/19/facts/4/label": "Executor initializer", "/versions/19/facts/5/label": "Memory mechanism", "/versions/19/tables/0/title": "EXPLAIN labels in this source build", "/versions/19/related/1/label": "Using EXPLAIN", "/versions/19/related/2/label": "Parallel plans", "/versions/19/sections/0/title": "EXPLAIN names and attributes", "/versions/19/sections/1/title": "Memory and temporary storage", "/versions/19/sections/2/title": "Parallel execution and instrumentation", "/versions/19/sections/3/title": "Same-version manual discussion", "/versions/19/sections/4/title": "Examples from this manual build", "/versions/19/sections/5/title": "Executor implementation notes", "/versions/19/sections/6/title": "EXPLAIN identity in core source", "/versions/19/memory/description": "The node passes work_mem to tuplesort. Sorting can use memory or temporary files; the actual method and space use depend on the input and plan.", "/versions/19/sections/0/paragraphs/0": "Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.", "/versions/19/sections/0/paragraphs/1": "Text names recorded by this source: Incremental Sort.", "/versions/19/sections/0/paragraphs/2": "Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node.", "/versions/19/sections/1/paragraphs/0": "The node passes work_mem to tuplesort. Sorting can use memory or temporary files; the actual method and space use depend on the input and plan.", "/versions/19/sections/1/paragraphs/1": "Incremental sort may be more efficient than plain sort, particularly on large datasets, as it reduces the amount of data to sort at once, making it more likely it fits into work_mem (eliminating the need to spill to disk). But the main advantage of incremental sort is that it can start producing rows early, before sorting the whole dataset, which is a significant benefit especially for queries with LIMIT.", "/versions/19/sections/1/paragraphs/2": "Because incremental sort processes (potentially many) sort batches, we need to capture tuplesort stats each time we finalize a sort state. This summary data is later used for EXPLAIN ANALYZE output.", "/versions/19/sections/2/paragraphs/0": "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.", "/versions/19/sections/2/paragraphs/1": "Callbacks in this build: ExecIncrementalSortEstimate, ExecIncrementalSortInitializeDSM, ExecIncrementalSortInitializeWorker, ExecIncrementalSortRetrieveInstrumentation.", "/versions/19/sections/3/paragraphs/0": "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:", "/versions/19/sections/5/paragraphs/0": "nodeIncrementalSort.c Routines to handle incremental sorting of relations.", "/versions/19/sections/5/paragraphs/1": "Incremental sort is an optimized variant of multikey sort for cases when the input is already sorted by a prefix of the sort keys. For example when a sort by (key1, key2 ... keyN) is requested, and the input is already sorted by (key1, key2 ... keyM), M < N, we can divide the input into groups where keys (key1, ... keyM) are equal, and only sort on the remaining columns.", "/versions/19/sections/5/paragraphs/2": "Consider the following example. We have input tuples consisting of two integers (X, Y) already presorted by X, while it's required to sort them by both X and Y. Let input tuples be following.", "/versions/19/sections/5/paragraphs/3": "An incremental sort algorithm would split the input into the following groups, which have equal X, and then sort them by Y individually:", "/versions/19/sections/5/paragraphs/4": "After sorting these groups and putting them altogether, we would get the following result which is sorted by X and Y, as requested:", "/versions/19/tables/0/columns/0/label": "Text-format label", "/versions/19/tables/0/columns/1/label": "Structured node identity", "/versions/19/sections/4/blocks/0/paragraphs/0": "Example copied from the PostgreSQL 19beta4 manual; it was not executed for this collection.", "/versions/19/sections/4/blocks/0/paragraphs/1": "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:"}, "fallback_fields": [], "source_language": "en", "original_snapshot_sha256": "f6dd20027de3dad06be45e38ad18de0add8f3420d91cb56bacd35f7eb485ac2a"}, "evidence_kind": "source and documentation", "explain_names": ["Incremental Sort"], "partial_modes": [], "comparison_data": {"node_tag": "T_IncrementalSort", "strategies": [], "text_names": ["Incremental Sort"], "initializer": "ExecInitIncrementalSort", "partial_modes": [], "memory_mechanism": "tuplesort", "parallel_callbacks": ["ExecIncrementalSortEstimate", "ExecIncrementalSortInitializeDSM", "ExecIncrementalSortInitializeWorker", "ExecIncrementalSortRetrieveInstrumentation"]}, "comparison_hash": "28d8e33452af10dcac50fa98fa4c5c6f639be663ae15b475f003e7c287e678f4", "explain_prefixes": ["Parallel", "Async"], "runtime_verified": false, "source_inventory": {"explain": "src/backend/commands/explain.c", "executor": "src/backend/executor/execProcnode.c", "implementation": "src/backend/executor/nodeIncrementalSort.c"}, "parallel_callbacks": ["ExecIncrementalSortEstimate", "ExecIncrementalSortInitializeDSM", "ExecIncrementalSortInitializeWorker", "ExecIncrementalSortRetrieveInstrumentation"]}, "20": {"facts": [{"label": "\u6838\u5fc3\u8282\u70b9\u6807\u7b7e", "value": "T_IncrementalSort"}, {"label": "\u7ed3\u6784\u5316 EXPLAIN \u8282\u70b9\u7c7b\u578b", "value": "Incremental Sort"}, {"label": "\u8f93\u5165", "value": "\u4e00\u4e2a\u90e8\u5206\u6709\u5e8f\u7684\u5b50\u8ba1\u5212"}, {"label": "\u8f93\u51fa", "value": "\u6309\u5b8c\u6574\u6392\u5e8f\u952e\u6392\u5e8f\u7684\u5143\u7ec4"}, {"label": "\u6267\u884c\u5668\u521d\u59cb\u5316\u51fd\u6570", "value": "ExecInitIncrementalSort"}, {"label": "\u5185\u5b58\u673a\u5236", "value": "tuplesort"}], "memory": {"evidence": [{"url": "https://ftp.postgresql.org/pub/snapshot/dev/postgresql-snapshot.tar.bz2", "path": "src/backend/executor/nodeIncrementalSort.c", "label": "src/backend/executor/nodeIncrementalSort.c", "sha256": "e6d51bf1a7631291c3f80c8dc1977506f1ad14af2908a338e9dc0e3f4b240a79", "archive_sha256": "4d3346909b201ac1648232cf290462a7070c119326f56196f1f0253ed80fae41"}, {"url": "https://ftp.postgresql.org/pub/snapshot/dev/postgresql-snapshot.tar.bz2", "path": "src/backend/utils/sort/tuplesort.c", "label": "src/backend/utils/sort/tuplesort.c", "sha256": "dc140a5018871fe263b585f4e8a7c9ab364b7d9533a6188b4279ab9ce3135641", "archive_sha256": "4d3346909b201ac1648232cf290462a7070c119326f56196f1f0253ed80fae41"}], "mechanism": "tuplesort", "description": "\u6b64\u8282\u70b9\u5c06 work_mem \u4f20\u7ed9 tuplesort\u3002\u6392\u5e8f\u53ef\u4f7f\u7528\u5185\u5b58\u6216\u4e34\u65f6\u6587\u4ef6\uff1b\u5b9e\u9645\u65b9\u6cd5\u548c\u7a7a\u95f4\u7528\u91cf\u53d6\u51b3\u4e8e\u8f93\u5165\u53ca\u8ba1\u5212\u3002", "source_notes": ["Incremental sort may be more efficient than plain sort, particularly on large datasets, as it reduces the amount of data to sort at once, making it more likely it fits into work_mem (eliminating the need to spill to disk). But the main advantage of incremental sort is that it can start producing rows early, before sorting the whole dataset, which is a significant benefit especially for queries with LIMIT.", "Because incremental sort processes (potentially many) sort batches, we need to capture tuplesort stats each time we finalize a sort state. This summary data is later used for EXPLAIN ANALYZE output."]}, "tables": [{"key": "explain-labels", "rows": [{"label": "Incremental Sort", "identity": "Incremental Sort"}], "title": "\u672c\u6784\u5efa\u4e2d\u7684 EXPLAIN \u6807\u7b7e", "columns": [{"key": "label", "label": "\u6587\u672c\u683c\u5f0f\u6807\u7b7e"}, {"key": "identity", "label": "\u7ed3\u6784\u5316\u8282\u70b9\u6807\u8bc6"}]}], "related": [{"url": "/wiki/sql/explain/?v=20", "label": "EXPLAIN"}, {"url": "/docs/devel/using-explain.html", "label": "\u4f7f\u7528 EXPLAIN"}, {"url": "/docs/devel/parallel-plans.html", "label": "\u5e76\u884c\u8ba1\u5212"}, {"url": "/wiki/guc/enable_incremental_sort/?v=20", "label": "enable_incremental_sort"}, {"url": "/wiki/guc/work_mem/?v=20", "label": "work_mem"}], "release": {"ref": "PostgreSQL 20devel source archive", "label": "20devel", "major": "20", "channel": "devel", "revision": "4d3346909b201ac1648232cf290462a7070c119326f56196f1f0253ed80fae41", "source_url": "https://ftp.postgresql.org/pub/snapshot/dev/postgresql-snapshot.tar.bz2", "source_snapshot_utc": "26-Sep-2026 20:22"}, "sources": [{"url": "https://ftp.postgresql.org/pub/snapshot/dev/postgresql-snapshot.tar.bz2", "line": 1537, "path": "src/backend/commands/explain.c", "label": "src/backend/commands/explain.c:1537", "sha256": "13402758013520451539427b5993db06d463ca11c4e2d4cc5444e82367688077", "archive_sha256": "4d3346909b201ac1648232cf290462a7070c119326f56196f1f0253ed80fae41"}, {"url": "https://ftp.postgresql.org/pub/snapshot/dev/postgresql-snapshot.tar.bz2", "line": 325, "path": "src/backend/executor/execProcnode.c", "label": "src/backend/executor/execProcnode.c:325", "sha256": "5e39b2037bed672da55104229ecc32da5abde44c26bcad01479edcfa044d09ed", "archive_sha256": "4d3346909b201ac1648232cf290462a7070c119326f56196f1f0253ed80fae41"}, {"url": "https://ftp.postgresql.org/pub/snapshot/dev/postgresql-snapshot.tar.bz2", "path": "src/backend/executor/nodeIncrementalSort.c", "label": "src/backend/executor/nodeIncrementalSort.c", "sha256": "e6d51bf1a7631291c3f80c8dc1977506f1ad14af2908a338e9dc0e3f4b240a79", "archive_sha256": "4d3346909b201ac1648232cf290462a7070c119326f56196f1f0253ed80fae41"}, {"url": "https://ftp.postgresql.org/pub/snapshot/dev/postgresql-snapshot.tar.bz2", "path": "src/include/nodes/plannodes.h", "label": "src/include/nodes/plannodes.h", "sha256": "7a94ed1652f0d74d50c39971d1cd3e8051dbc0d6058f31b6de71a433ca343521", "archive_sha256": "4d3346909b201ac1648232cf290462a7070c119326f56196f1f0253ed80fae41"}, {"url": "https://ftp.postgresql.org/pub/snapshot/dev/postgresql-snapshot.tar.bz2", "path": "src/backend/utils/sort/tuplesort.c", "label": "src/backend/utils/sort/tuplesort.c", "sha256": "dc140a5018871fe263b585f4e8a7c9ab364b7d9533a6188b4279ab9ce3135641", "archive_sha256": "4d3346909b201ac1648232cf290462a7070c119326f56196f1f0253ed80fae41"}, {"url": "https://pg.center/docs/devel/using-explain.html#USING-EXPLAIN-BASICS", "path": "using-explain.html", "label": "PostgreSQL 20devel \u00b7 using-explain", "sha256": "99cfea3035876ea63f88b75ba8c964b51a32a70606544e09f769c0b60a234b31", "language": "en", "original_url": "/docs/devel/using-explain.html#USING-EXPLAIN-BASICS"}], "node_tag": "T_IncrementalSort", "sections": [{"title": "EXPLAIN \u540d\u79f0\u4e0e\u5c5e\u6027", "paragraphs": ["\u7ed3\u6784\u5316\u683c\u5f0f\u4f7f\u7528\u4e0a\u8ff0 Node Type\u3002\u6587\u672c\u683c\u5f0f\u540d\u79f0\u8fd8\u53ef\u80fd\u5305\u542b\u64cd\u4f5c\u3001\u7b56\u7565\u3001\u8fde\u63a5\u7c7b\u578b\u3001\u626b\u63cf\u65b9\u5411\u6216\u805a\u5408\u9636\u6bb5\u5c5e\u6027\u3002", "\u6b64\u6e90\u7801\u8bb0\u5f55\u7684\u6587\u672c\u540d\u79f0\uff1aIncremental Sort.", "\u5e76\u884c\u611f\u77e5\u4e0e\u5e76\u884c\u5b89\u5168\u662f\u4e0d\u540c\u7684\u8ba1\u5212\u5c5e\u6027\u3002\u5728\u5e76\u884c\u5de5\u4f5c\u8fdb\u7a0b\u5185\u8fd0\u884c\u7684\u8282\u70b9\u4e0d\u4e00\u5b9a\u662f\u5e76\u884c\u611f\u77e5\u8282\u70b9\u3002"]}, {"title": "\u5185\u5b58\u4e0e\u4e34\u65f6\u5b58\u50a8", "paragraphs": ["\u6b64\u8282\u70b9\u5c06 work_mem \u4f20\u7ed9 tuplesort\u3002\u6392\u5e8f\u53ef\u4f7f\u7528\u5185\u5b58\u6216\u4e34\u65f6\u6587\u4ef6\uff1b\u5b9e\u9645\u65b9\u6cd5\u548c\u7a7a\u95f4\u7528\u91cf\u53d6\u51b3\u4e8e\u8f93\u5165\u53ca\u8ba1\u5212\u3002", "\u589e\u91cf\u6392\u5e8f\u53ef\u80fd\u6bd4\u666e\u901a\u6392\u5e8f\u66f4\u9ad8\u6548\uff0c\u5c24\u5176\u5bf9\u4e8e\u5927\u578b\u6570\u636e\u96c6\uff0c\u56e0\u4e3a\u5b83\u51cf\u5c11\u4e86\u6bcf\u6b21\u6392\u5e8f\u7684\u6570\u636e\u91cf\uff0c\u66f4\u53ef\u80fd\u653e\u5165 work_mem\uff0c\u4ece\u800c\u907f\u514d\u843d\u76d8\u3002\u4f46\u5176\u4e3b\u8981\u4f18\u52bf\u662f\u5728\u6574\u4e2a\u6570\u636e\u96c6\u6392\u5e8f\u5b8c\u6210\u4e4b\u524d\u5c31\u80fd\u5f00\u59cb\u8f93\u51fa\u884c\uff0c\u8fd9\u5bf9\u5e26 LIMIT \u7684\u67e5\u8be2\u5c24\u5176\u6709\u5229\u3002", "\u589e\u91cf\u6392\u5e8f\u53ef\u80fd\u5904\u7406\u8bb8\u591a\u6392\u5e8f\u6279\u6b21\uff0c\u56e0\u6b64\u6bcf\u6b21\u7ed3\u675f\u4e00\u4e2a\u6392\u5e8f\u72b6\u6001\u65f6\u90fd\u8981\u8bb0\u5f55 tuplesort \u7edf\u8ba1\u4fe1\u606f\u3002\u8fd9\u4e9b\u6c47\u603b\u6570\u636e\u968f\u540e\u7528\u4e8e EXPLAIN ANALYZE \u8f93\u51fa\u3002"]}, {"title": "\u5e76\u884c\u6267\u884c\u4e0e\u8fd0\u884c\u4fe1\u606f\u91c7\u96c6", "paragraphs": ["\u4ee5\u4e0b\u6e90\u7801\u56de\u8c03\u53ef\u4ee5\u534f\u8c03\u6267\u884c\u6216\u6536\u96c6\u5de5\u4f5c\u8fdb\u7a0b\u7684\u6d4b\u91cf\u6570\u636e\u3002\u56de\u8c03\u5b58\u5728\u4e0d\u4ee3\u8868\u8be5\u8282\u70b9\u666e\u904d\u652f\u6301\u5171\u4eab\u5e76\u884c\u626b\u63cf\u6216\u5171\u4eab\u72b6\u6001\u3002", "\u6b64\u6784\u5efa\u7684\u56de\u8c03\uff1aExecIncrementalSortEstimate, ExecIncrementalSortInitializeDSM, ExecIncrementalSortInitializeWorker, ExecIncrementalSortRetrieveInstrumentation."]}, {"title": "\u540c\u7248\u672c\u624b\u518c\u8bf4\u660e", "paragraphs": ["\u5982\u679c\u8ba1\u5212\u4e2d\u7684\u67d0\u4e00\u90e8\u5206\u5df2\u7ecf\u4fdd\u8bc1\u4e86\u6240\u9700\u6392\u5e8f\u952e\u524d\u7f00\u7684\u987a\u5e8f\uff0c\u89c4\u5212\u5668\u4e5f\u53ef\u80fd\u6539\u7528 Incremental Sort \u6b65\u9aa4\uff1a"]}, {"title": "\u672c\u7248\u624b\u518c\u4e2d\u7684\u793a\u4f8b", "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   ->  Incremental Sort  (cost=19.35..2033.39 rows=10000 width=244)\n         Sort Key: hundred, ten\n         Presorted Key: hundred\n         Estimated Groups: 100\n         ->  Index Scan using tenk1_hundred on tenk1  (cost=0.29..1574.20 rows=10000 width=244)", "source": {"url": "/docs/devel/using-explain.html#USING-EXPLAIN-BASICS", "path": "using-explain.html", "label": "PostgreSQL 20devel \u00b7 using-explain", "sha256": "99cfea3035876ea63f88b75ba8c964b51a32a70606544e09f769c0b60a234b31"}, "paragraphs": ["\u793a\u4f8b\u6458\u81ea PostgreSQL 20devel \u624b\u518c\uff1b\u672c\u767e\u79d1\u672a\u5b9e\u9645\u6267\u884c\u6b64\u793a\u4f8b\u3002", "\u5982\u679c\u8ba1\u5212\u4e2d\u7684\u67d0\u4e00\u90e8\u5206\u5df2\u7ecf\u4fdd\u8bc1\u4e86\u6240\u9700\u6392\u5e8f\u952e\u524d\u7f00\u7684\u987a\u5e8f\uff0c\u89c4\u5212\u5668\u4e5f\u53ef\u80fd\u6539\u7528 Incremental Sort \u6b65\u9aa4\uff1a"]}]}, {"title": "\u6267\u884c\u5668\u5b9e\u73b0\u8bf4\u660e", "paragraphs": ["nodeIncrementalSort.c\uff1a\u5904\u7406\u5173\u7cfb\u589e\u91cf\u6392\u5e8f\u7684\u4f8b\u7a0b\u3002", "\u589e\u91cf\u6392\u5e8f\u662f\u591a\u952e\u6392\u5e8f\u7684\u4e00\u79cd\u4f18\u5316\u5f62\u5f0f\uff0c\u9002\u7528\u4e8e\u8f93\u5165\u5df2\u6309\u6392\u5e8f\u952e\u524d\u7f00\u6392\u597d\u5e8f\u7684\u60c5\u51b5\u3002\u4f8b\u5982\uff0c\u8981\u6c42\u6309 (key1, key2 ... keyN) \u6392\u5e8f\uff0c\u800c\u8f93\u5165\u5df2\u6309 (key1, key2 ... keyM) \u6392\u5e8f\uff0c\u4e14 M < N\uff0c\u5219\u53ef\u5c06\u8f93\u5165\u5212\u5206\u4e3a (key1, ... keyM) \u76f8\u7b49\u7684\u5206\u7ec4\uff0c\u53ea\u5bf9\u5269\u4f59\u5217\u6392\u5e8f\u3002", "\u8003\u8651\u4ee5\u4e0b\u793a\u4f8b\uff1a\u8f93\u5165\u5143\u7ec4\u7531\u4e24\u4e2a\u6574\u6570 (X, Y) \u7ec4\u6210\uff0c\u5df2\u7ecf\u6309 X \u9884\u6392\u5e8f\uff0c\u800c\u73b0\u5728\u9700\u8981\u540c\u65f6\u6309 X \u548c Y \u6392\u5e8f\u3002\u8f93\u5165\u5143\u7ec4\u5982\u4e0b\u3002", "\u589e\u91cf\u6392\u5e8f\u7b97\u6cd5\u4f1a\u6309 X \u76f8\u7b49\u5c06\u8f93\u5165\u62c6\u5206\u4e3a\u4ee5\u4e0b\u5404\u7ec4\uff0c\u518d\u5206\u522b\u6309 Y \u6392\u5e8f\uff1a", "\u5bf9\u8fd9\u4e9b\u5206\u7ec4\u5206\u522b\u6392\u5e8f\u540e\uff0c\u5c06\u5176\u62fc\u63a5\u8d77\u6765\uff0c\u5373\u53ef\u5f97\u5230\u4e0b\u9762\u6309\u8981\u6c42\u540c\u65f6\u6309 X \u548c Y \u6392\u5e8f\u7684\u7ed3\u679c\uff1a"]}, {"code": "case T_IncrementalSort:\n\t\t\tpname = sname = \"Incremental Sort\";\n\t\t\tbreak;", "title": "\u6838\u5fc3\u6e90\u7801\u4e2d\u7684 EXPLAIN \u6807\u8bc6"}], "strategies": [], "description": ["\u5bf9\u5171\u4eab\u5df2\u6709\u6392\u5e8f\u952e\u524d\u7f00\u7684\u5206\u7ec4\u5206\u522b\u6392\u5e8f\uff0c\u6269\u5c55\u8f93\u5165\u5df2\u6709\u7684\u6392\u5e8f\u987a\u5e8f\u3002"], "localization": {"status": "complete", "sources": [{"url": "/docs/devel/using-explain.html", "method": "same-major semantic node", "sha256": "2744ee0e88d132c504bf5e102765edaabd393eb12c59294093db6d90b26dd65c", "language": "zh", "matched_nodes": ["#USING-EXPLAIN/div[7]/p[29]"]}], "language": "zh", "original_text": {"/summary": "Extends an existing ordering by sorting groups that share the presorted key prefix.", "/category": "Ordering", "/versions/20/description/0": "Extends an existing ordering by sorting groups that share the presorted key prefix.", "/versions/20/facts/0/label": "Core node tag", "/versions/20/facts/1/label": "Structured EXPLAIN Node Type", "/versions/20/facts/2/label": "Inputs", "/versions/20/facts/2/value": "One partly ordered child plan", "/versions/20/facts/3/label": "Output", "/versions/20/facts/3/value": "Tuples ordered by the full sort key", "/versions/20/facts/4/label": "Executor initializer", "/versions/20/facts/5/label": "Memory mechanism", "/versions/20/tables/0/title": "EXPLAIN labels in this source build", "/versions/20/related/1/label": "Using EXPLAIN", "/versions/20/related/2/label": "Parallel plans", "/versions/20/sections/0/title": "EXPLAIN names and attributes", "/versions/20/sections/1/title": "Memory and temporary storage", "/versions/20/sections/2/title": "Parallel execution and instrumentation", "/versions/20/sections/3/title": "Same-version manual discussion", "/versions/20/sections/4/title": "Examples from this manual build", "/versions/20/sections/5/title": "Executor implementation notes", "/versions/20/sections/6/title": "EXPLAIN identity in core source", "/versions/20/memory/description": "The node passes work_mem to tuplesort. Sorting can use memory or temporary files; the actual method and space use depend on the input and plan.", "/versions/20/sections/0/paragraphs/0": "Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.", "/versions/20/sections/0/paragraphs/1": "Text names recorded by this source: Incremental Sort.", "/versions/20/sections/0/paragraphs/2": "Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node.", "/versions/20/sections/1/paragraphs/0": "The node passes work_mem to tuplesort. Sorting can use memory or temporary files; the actual method and space use depend on the input and plan.", "/versions/20/sections/1/paragraphs/1": "Incremental sort may be more efficient than plain sort, particularly on large datasets, as it reduces the amount of data to sort at once, making it more likely it fits into work_mem (eliminating the need to spill to disk). But the main advantage of incremental sort is that it can start producing rows early, before sorting the whole dataset, which is a significant benefit especially for queries with LIMIT.", "/versions/20/sections/1/paragraphs/2": "Because incremental sort processes (potentially many) sort batches, we need to capture tuplesort stats each time we finalize a sort state. This summary data is later used for EXPLAIN ANALYZE output.", "/versions/20/sections/2/paragraphs/0": "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.", "/versions/20/sections/2/paragraphs/1": "Callbacks in this build: ExecIncrementalSortEstimate, ExecIncrementalSortInitializeDSM, ExecIncrementalSortInitializeWorker, ExecIncrementalSortRetrieveInstrumentation.", "/versions/20/sections/3/paragraphs/0": "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:", "/versions/20/sections/5/paragraphs/0": "nodeIncrementalSort.c Routines to handle incremental sorting of relations.", "/versions/20/sections/5/paragraphs/1": "Incremental sort is an optimized variant of multikey sort for cases when the input is already sorted by a prefix of the sort keys. For example when a sort by (key1, key2 ... keyN) is requested, and the input is already sorted by (key1, key2 ... keyM), M < N, we can divide the input into groups where keys (key1, ... keyM) are equal, and only sort on the remaining columns.", "/versions/20/sections/5/paragraphs/2": "Consider the following example. We have input tuples consisting of two integers (X, Y) already presorted by X, while it's required to sort them by both X and Y. Let input tuples be following.", "/versions/20/sections/5/paragraphs/3": "An incremental sort algorithm would split the input into the following groups, which have equal X, and then sort them by Y individually:", "/versions/20/sections/5/paragraphs/4": "After sorting these groups and putting them altogether, we would get the following result which is sorted by X and Y, as requested:", "/versions/20/tables/0/columns/0/label": "Text-format label", "/versions/20/tables/0/columns/1/label": "Structured node identity", "/versions/20/sections/4/blocks/0/paragraphs/0": "Example copied from the PostgreSQL 20devel manual; it was not executed for this collection.", "/versions/20/sections/4/blocks/0/paragraphs/1": "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:"}, "fallback_fields": [], "source_language": "en", "original_snapshot_sha256": "906fff628d3f199744cd8d7a0895dffc7f5535d2bcb899564fc08837916e5fef"}, "evidence_kind": "source and documentation", "explain_names": ["Incremental Sort"], "partial_modes": [], "comparison_data": {"node_tag": "T_IncrementalSort", "strategies": [], "text_names": ["Incremental Sort"], "initializer": "ExecInitIncrementalSort", "partial_modes": [], "memory_mechanism": "tuplesort", "parallel_callbacks": ["ExecIncrementalSortEstimate", "ExecIncrementalSortInitializeDSM", "ExecIncrementalSortInitializeWorker", "ExecIncrementalSortRetrieveInstrumentation"]}, "comparison_hash": "28d8e33452af10dcac50fa98fa4c5c6f639be663ae15b475f003e7c287e678f4", "explain_prefixes": ["Parallel", "Async"], "runtime_verified": false, "source_inventory": {"explain": "src/backend/commands/explain.c", "executor": "src/backend/executor/execProcnode.c", "implementation": "src/backend/executor/nodeIncrementalSort.c"}, "parallel_callbacks": ["ExecIncrementalSortEstimate", "ExecIncrementalSortInitializeDSM", "ExecIncrementalSortInitializeWorker", "ExecIncrementalSortRetrieveInstrumentation"]}}}, "snapshot": {"facts": [{"label": "\u6838\u5fc3\u8282\u70b9\u6807\u7b7e", "value": "T_IncrementalSort"}, {"label": "\u7ed3\u6784\u5316 EXPLAIN \u8282\u70b9\u7c7b\u578b", "value": "Incremental Sort"}, {"label": "\u8f93\u5165", "value": "\u4e00\u4e2a\u90e8\u5206\u6709\u5e8f\u7684\u5b50\u8ba1\u5212"}, {"label": "\u8f93\u51fa", "value": "\u6309\u5b8c\u6574\u6392\u5e8f\u952e\u6392\u5e8f\u7684\u5143\u7ec4"}, {"label": "\u6267\u884c\u5668\u521d\u59cb\u5316\u51fd\u6570", "value": "ExecInitIncrementalSort"}, {"label": "\u5185\u5b58\u673a\u5236", "value": "tuplesort"}], "memory": {"evidence": [{"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "path": "src/backend/executor/nodeIncrementalSort.c", "label": "src/backend/executor/nodeIncrementalSort.c", "sha256": "9fd15ce79cd3dd5c131c5bfb322039213cba9232fdfaa5b53e5f40e7d17195cf", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "path": "src/backend/utils/sort/tuplesort.c", "label": "src/backend/utils/sort/tuplesort.c", "sha256": "509d4cef598613bbf0725f697e1e1e33f3dfc8debed20169a6c4bf1ac9e5c2e3", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}], "mechanism": "tuplesort", "description": "\u6b64\u8282\u70b9\u5c06 work_mem \u4f20\u7ed9 tuplesort\u3002\u6392\u5e8f\u53ef\u4f7f\u7528\u5185\u5b58\u6216\u4e34\u65f6\u6587\u4ef6\uff1b\u5b9e\u9645\u65b9\u6cd5\u548c\u7a7a\u95f4\u7528\u91cf\u53d6\u51b3\u4e8e\u8f93\u5165\u53ca\u8ba1\u5212\u3002", "source_notes": ["Incremental sort may be more efficient than plain sort, particularly on large datasets, as it reduces the amount of data to sort at once, making it more likely it fits into work_mem (eliminating the need to spill to disk). But the main advantage of incremental sort is that it can start producing rows early, before sorting the whole dataset, which is a significant benefit especially for queries with LIMIT.", "Because incremental sort processes (potentially many) sort batches, we need to capture tuplesort stats each time we finalize a sort state. This summary data is later used for EXPLAIN ANALYZE output."]}, "tables": [{"key": "explain-labels", "rows": [{"label": "Incremental Sort", "identity": "Incremental Sort"}], "title": "\u672c\u6784\u5efa\u4e2d\u7684 EXPLAIN \u6807\u7b7e", "columns": [{"key": "label", "label": "\u6587\u672c\u683c\u5f0f\u6807\u7b7e"}, {"key": "identity", "label": "\u7ed3\u6784\u5316\u8282\u70b9\u6807\u8bc6"}]}], "related": [{"url": "/wiki/sql/explain/?v=18", "label": "EXPLAIN"}, {"url": "/docs/18/using-explain.html", "label": "\u4f7f\u7528 EXPLAIN"}, {"url": "/docs/18/parallel-plans.html", "label": "\u5e76\u884c\u8ba1\u5212"}, {"url": "/wiki/guc/enable_incremental_sort/?v=18", "label": "enable_incremental_sort"}, {"url": "/wiki/guc/work_mem/?v=18", "label": "work_mem"}], "release": {"ref": "PostgreSQL 18.6 source archive", "label": "18.6", "major": "18", "channel": "stable", "revision": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f", "source_url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "line": 1525, "path": "src/backend/commands/explain.c", "label": "src/backend/commands/explain.c:1525", "sha256": "34c86d6070224a0e981efef51f79101d6d505e5874f1684ace183034bab14bb4", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "line": 325, "path": "src/backend/executor/execProcnode.c", "label": "src/backend/executor/execProcnode.c:325", "sha256": "f8a06a3f539077249b20664b2812433db6d7bd12b2c0ca633525db43d06f112a", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "path": "src/backend/executor/nodeIncrementalSort.c", "label": "src/backend/executor/nodeIncrementalSort.c", "sha256": "9fd15ce79cd3dd5c131c5bfb322039213cba9232fdfaa5b53e5f40e7d17195cf", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "path": "src/include/nodes/plannodes.h", "label": "src/include/nodes/plannodes.h", "sha256": "52422b327a8049fbbb20d8b96008a0fc0a6fafa60f7eff3c695d5b2e83830120", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "path": "src/backend/utils/sort/tuplesort.c", "label": "src/backend/utils/sort/tuplesort.c", "sha256": "509d4cef598613bbf0725f697e1e1e33f3dfc8debed20169a6c4bf1ac9e5c2e3", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "https://pg.center/docs/18/using-explain.html#USING-EXPLAIN-BASICS", "path": "using-explain.html", "label": "PostgreSQL 18.6 \u00b7 using-explain", "sha256": "60040c30180093418a0affe56dd27dff9df2504b705b38039589e458bf5c31ed", "language": "en", "original_url": "/docs/18/using-explain.html#USING-EXPLAIN-BASICS"}], "node_tag": "T_IncrementalSort", "sections": [{"title": "EXPLAIN \u540d\u79f0\u4e0e\u5c5e\u6027", "paragraphs": ["\u7ed3\u6784\u5316\u683c\u5f0f\u4f7f\u7528\u4e0a\u8ff0 Node Type\u3002\u6587\u672c\u683c\u5f0f\u540d\u79f0\u8fd8\u53ef\u80fd\u5305\u542b\u64cd\u4f5c\u3001\u7b56\u7565\u3001\u8fde\u63a5\u7c7b\u578b\u3001\u626b\u63cf\u65b9\u5411\u6216\u805a\u5408\u9636\u6bb5\u5c5e\u6027\u3002", "\u6b64\u6e90\u7801\u8bb0\u5f55\u7684\u6587\u672c\u540d\u79f0\uff1aIncremental Sort.", "\u5e76\u884c\u611f\u77e5\u4e0e\u5e76\u884c\u5b89\u5168\u662f\u4e0d\u540c\u7684\u8ba1\u5212\u5c5e\u6027\u3002\u5728\u5e76\u884c\u5de5\u4f5c\u8fdb\u7a0b\u5185\u8fd0\u884c\u7684\u8282\u70b9\u4e0d\u4e00\u5b9a\u662f\u5e76\u884c\u611f\u77e5\u8282\u70b9\u3002"]}, {"title": "\u5185\u5b58\u4e0e\u4e34\u65f6\u5b58\u50a8", "paragraphs": ["\u6b64\u8282\u70b9\u5c06 work_mem \u4f20\u7ed9 tuplesort\u3002\u6392\u5e8f\u53ef\u4f7f\u7528\u5185\u5b58\u6216\u4e34\u65f6\u6587\u4ef6\uff1b\u5b9e\u9645\u65b9\u6cd5\u548c\u7a7a\u95f4\u7528\u91cf\u53d6\u51b3\u4e8e\u8f93\u5165\u53ca\u8ba1\u5212\u3002", "\u589e\u91cf\u6392\u5e8f\u53ef\u80fd\u6bd4\u666e\u901a\u6392\u5e8f\u66f4\u9ad8\u6548\uff0c\u5c24\u5176\u5bf9\u4e8e\u5927\u578b\u6570\u636e\u96c6\uff0c\u56e0\u4e3a\u5b83\u51cf\u5c11\u4e86\u6bcf\u6b21\u6392\u5e8f\u7684\u6570\u636e\u91cf\uff0c\u66f4\u53ef\u80fd\u653e\u5165 work_mem\uff0c\u4ece\u800c\u907f\u514d\u843d\u76d8\u3002\u4f46\u5176\u4e3b\u8981\u4f18\u52bf\u662f\u5728\u6574\u4e2a\u6570\u636e\u96c6\u6392\u5e8f\u5b8c\u6210\u4e4b\u524d\u5c31\u80fd\u5f00\u59cb\u8f93\u51fa\u884c\uff0c\u8fd9\u5bf9\u5e26 LIMIT \u7684\u67e5\u8be2\u5c24\u5176\u6709\u5229\u3002", "\u589e\u91cf\u6392\u5e8f\u53ef\u80fd\u5904\u7406\u8bb8\u591a\u6392\u5e8f\u6279\u6b21\uff0c\u56e0\u6b64\u6bcf\u6b21\u7ed3\u675f\u4e00\u4e2a\u6392\u5e8f\u72b6\u6001\u65f6\u90fd\u8981\u8bb0\u5f55 tuplesort \u7edf\u8ba1\u4fe1\u606f\u3002\u8fd9\u4e9b\u6c47\u603b\u6570\u636e\u968f\u540e\u7528\u4e8e EXPLAIN ANALYZE \u8f93\u51fa\u3002"]}, {"title": "\u5e76\u884c\u6267\u884c\u4e0e\u8fd0\u884c\u4fe1\u606f\u91c7\u96c6", "paragraphs": ["\u4ee5\u4e0b\u6e90\u7801\u56de\u8c03\u53ef\u4ee5\u534f\u8c03\u6267\u884c\u6216\u6536\u96c6\u5de5\u4f5c\u8fdb\u7a0b\u7684\u6d4b\u91cf\u6570\u636e\u3002\u56de\u8c03\u5b58\u5728\u4e0d\u4ee3\u8868\u8be5\u8282\u70b9\u666e\u904d\u652f\u6301\u5171\u4eab\u5e76\u884c\u626b\u63cf\u6216\u5171\u4eab\u72b6\u6001\u3002", "\u6b64\u6784\u5efa\u7684\u56de\u8c03\uff1aExecIncrementalSortEstimate, ExecIncrementalSortInitializeDSM, ExecIncrementalSortInitializeWorker, ExecIncrementalSortRetrieveInstrumentation."]}, {"title": "\u540c\u7248\u672c\u624b\u518c\u8bf4\u660e", "paragraphs": ["\u5982\u679c\u8ba1\u5212\u4e2d\u7684\u67d0\u4e00\u90e8\u5206\u5df2\u7ecf\u4fdd\u8bc1\u4e86\u6240\u9700\u6392\u5e8f\u952e\u524d\u7f00\u7684\u987a\u5e8f\uff0c\u89c4\u5212\u5668\u4e5f\u53ef\u80fd\u6539\u7528 Incremental Sort \u6b65\u9aa4\uff1a"]}, {"title": "\u672c\u7248\u624b\u518c\u4e2d\u7684\u793a\u4f8b", "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   ->  Incremental Sort  (cost=19.35..2033.39 rows=10000 width=244)\n         Sort Key: hundred, ten\n         Presorted Key: hundred\n         ->  Index Scan using tenk1_hundred on tenk1  (cost=0.29..1574.20 rows=10000 width=244)", "source": {"url": "/docs/18/using-explain.html#USING-EXPLAIN-BASICS", "path": "using-explain.html", "label": "PostgreSQL 18.6 \u00b7 using-explain", "sha256": "60040c30180093418a0affe56dd27dff9df2504b705b38039589e458bf5c31ed"}, "paragraphs": ["\u793a\u4f8b\u6458\u81ea PostgreSQL 18.6 \u624b\u518c\uff1b\u672c\u767e\u79d1\u672a\u5b9e\u9645\u6267\u884c\u6b64\u793a\u4f8b\u3002", "\u5982\u679c\u8ba1\u5212\u4e2d\u7684\u67d0\u4e00\u90e8\u5206\u5df2\u7ecf\u4fdd\u8bc1\u4e86\u6240\u9700\u6392\u5e8f\u952e\u524d\u7f00\u7684\u987a\u5e8f\uff0c\u89c4\u5212\u5668\u4e5f\u53ef\u80fd\u6539\u7528 Incremental Sort \u6b65\u9aa4\uff1a"]}]}, {"title": "\u6267\u884c\u5668\u5b9e\u73b0\u8bf4\u660e", "paragraphs": ["nodeIncrementalSort.c\uff1a\u5904\u7406\u5173\u7cfb\u589e\u91cf\u6392\u5e8f\u7684\u4f8b\u7a0b\u3002", "\u589e\u91cf\u6392\u5e8f\u662f\u591a\u952e\u6392\u5e8f\u7684\u4e00\u79cd\u4f18\u5316\u5f62\u5f0f\uff0c\u9002\u7528\u4e8e\u8f93\u5165\u5df2\u6309\u6392\u5e8f\u952e\u524d\u7f00\u6392\u597d\u5e8f\u7684\u60c5\u51b5\u3002\u4f8b\u5982\uff0c\u8981\u6c42\u6309 (key1, key2 ... keyN) \u6392\u5e8f\uff0c\u800c\u8f93\u5165\u5df2\u6309 (key1, key2 ... keyM) \u6392\u5e8f\uff0c\u4e14 M < N\uff0c\u5219\u53ef\u5c06\u8f93\u5165\u5212\u5206\u4e3a (key1, ... keyM) \u76f8\u7b49\u7684\u5206\u7ec4\uff0c\u53ea\u5bf9\u5269\u4f59\u5217\u6392\u5e8f\u3002", "\u8003\u8651\u4ee5\u4e0b\u793a\u4f8b\uff1a\u8f93\u5165\u5143\u7ec4\u7531\u4e24\u4e2a\u6574\u6570 (X, Y) \u7ec4\u6210\uff0c\u5df2\u7ecf\u6309 X \u9884\u6392\u5e8f\uff0c\u800c\u73b0\u5728\u9700\u8981\u540c\u65f6\u6309 X \u548c Y \u6392\u5e8f\u3002\u8f93\u5165\u5143\u7ec4\u5982\u4e0b\u3002", "\u589e\u91cf\u6392\u5e8f\u7b97\u6cd5\u4f1a\u6309 X \u76f8\u7b49\u5c06\u8f93\u5165\u62c6\u5206\u4e3a\u4ee5\u4e0b\u5404\u7ec4\uff0c\u518d\u5206\u522b\u6309 Y \u6392\u5e8f\uff1a", "\u5bf9\u8fd9\u4e9b\u5206\u7ec4\u5206\u522b\u6392\u5e8f\u540e\uff0c\u5c06\u5176\u62fc\u63a5\u8d77\u6765\uff0c\u5373\u53ef\u5f97\u5230\u4e0b\u9762\u6309\u8981\u6c42\u540c\u65f6\u6309 X \u548c Y \u6392\u5e8f\u7684\u7ed3\u679c\uff1a"]}, {"code": "case T_IncrementalSort:\n\t\t\tpname = sname = \"Incremental Sort\";\n\t\t\tbreak;", "title": "\u6838\u5fc3\u6e90\u7801\u4e2d\u7684 EXPLAIN \u6807\u8bc6"}], "strategies": [], "description": ["\u5bf9\u5171\u4eab\u5df2\u6709\u6392\u5e8f\u952e\u524d\u7f00\u7684\u5206\u7ec4\u5206\u522b\u6392\u5e8f\uff0c\u6269\u5c55\u8f93\u5165\u5df2\u6709\u7684\u6392\u5e8f\u987a\u5e8f\u3002"], "localization": {"status": "complete", "sources": [{"url": "/docs/18/using-explain.html", "method": "same-major semantic node", "sha256": "b8835ec9adbc70ec150667a6b5443f8d298222dc0cc8c2bd1abb1c1d64895904", "language": "zh", "matched_nodes": ["#USING-EXPLAIN/div[7]/p[29]"]}], "language": "zh", "original_text": {"/versions/18/description/0": "Extends an existing ordering by sorting groups that share the presorted key prefix.", "/versions/18/facts/0/label": "Core node tag", "/versions/18/facts/1/label": "Structured EXPLAIN Node Type", "/versions/18/facts/2/label": "Inputs", "/versions/18/facts/2/value": "One partly ordered child plan", "/versions/18/facts/3/label": "Output", "/versions/18/facts/3/value": "Tuples ordered by the full sort key", "/versions/18/facts/4/label": "Executor initializer", "/versions/18/facts/5/label": "Memory mechanism", "/versions/18/tables/0/title": "EXPLAIN labels in this source build", "/versions/18/related/1/label": "Using EXPLAIN", "/versions/18/related/2/label": "Parallel plans", "/versions/18/sections/0/title": "EXPLAIN names and attributes", "/versions/18/sections/1/title": "Memory and temporary storage", "/versions/18/sections/2/title": "Parallel execution and instrumentation", "/versions/18/sections/3/title": "Same-version manual discussion", "/versions/18/sections/4/title": "Examples from this manual build", "/versions/18/sections/5/title": "Executor implementation notes", "/versions/18/sections/6/title": "EXPLAIN identity in core source", "/versions/18/memory/description": "The node passes work_mem to tuplesort. Sorting can use memory or temporary files; the actual method and space use depend on the input and plan.", "/versions/18/sections/0/paragraphs/0": "Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.", "/versions/18/sections/0/paragraphs/1": "Text names recorded by this source: Incremental Sort.", "/versions/18/sections/0/paragraphs/2": "Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node.", "/versions/18/sections/1/paragraphs/0": "The node passes work_mem to tuplesort. Sorting can use memory or temporary files; the actual method and space use depend on the input and plan.", "/versions/18/sections/1/paragraphs/1": "Incremental sort may be more efficient than plain sort, particularly on large datasets, as it reduces the amount of data to sort at once, making it more likely it fits into work_mem (eliminating the need to spill to disk). But the main advantage of incremental sort is that it can start producing rows early, before sorting the whole dataset, which is a significant benefit especially for queries with LIMIT.", "/versions/18/sections/1/paragraphs/2": "Because incremental sort processes (potentially many) sort batches, we need to capture tuplesort stats each time we finalize a sort state. This summary data is later used for EXPLAIN ANALYZE output.", "/versions/18/sections/2/paragraphs/0": "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.", "/versions/18/sections/2/paragraphs/1": "Callbacks in this build: ExecIncrementalSortEstimate, ExecIncrementalSortInitializeDSM, ExecIncrementalSortInitializeWorker, ExecIncrementalSortRetrieveInstrumentation.", "/versions/18/sections/3/paragraphs/0": "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:", "/versions/18/sections/5/paragraphs/0": "nodeIncrementalSort.c Routines to handle incremental sorting of relations.", "/versions/18/sections/5/paragraphs/1": "Incremental sort is an optimized variant of multikey sort for cases when the input is already sorted by a prefix of the sort keys. For example when a sort by (key1, key2 ... keyN) is requested, and the input is already sorted by (key1, key2 ... keyM), M < N, we can divide the input into groups where keys (key1, ... keyM) are equal, and only sort on the remaining columns.", "/versions/18/sections/5/paragraphs/2": "Consider the following example. We have input tuples consisting of two integers (X, Y) already presorted by X, while it's required to sort them by both X and Y. Let input tuples be following.", "/versions/18/sections/5/paragraphs/3": "An incremental sort algorithm would split the input into the following groups, which have equal X, and then sort them by Y individually:", "/versions/18/sections/5/paragraphs/4": "After sorting these groups and putting them altogether, we would get the following result which is sorted by X and Y, as requested:", "/versions/18/tables/0/columns/0/label": "Text-format label", "/versions/18/tables/0/columns/1/label": "Structured node identity", "/versions/18/sections/4/blocks/0/paragraphs/0": "Example copied from the PostgreSQL 18.6 manual; it was not executed for this collection.", "/versions/18/sections/4/blocks/0/paragraphs/1": "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:"}, "fallback_fields": [], "source_language": "en", "original_snapshot_sha256": "e3f6e08bd43d692c547cef700107fe9837e03dd63bf94eb96065dfdba77e7446"}, "evidence_kind": "source and documentation", "explain_names": ["Incremental Sort"], "partial_modes": [], "comparison_data": {"node_tag": "T_IncrementalSort", "strategies": [], "text_names": ["Incremental Sort"], "initializer": "ExecInitIncrementalSort", "partial_modes": [], "memory_mechanism": "tuplesort", "parallel_callbacks": ["ExecIncrementalSortEstimate", "ExecIncrementalSortInitializeDSM", "ExecIncrementalSortInitializeWorker", "ExecIncrementalSortRetrieveInstrumentation"]}, "comparison_hash": "28d8e33452af10dcac50fa98fa4c5c6f639be663ae15b475f003e7c287e678f4", "explain_prefixes": ["Parallel", "Async"], "runtime_verified": false, "source_inventory": {"explain": "src/backend/commands/explain.c", "executor": "src/backend/executor/execProcnode.c", "implementation": "src/backend/executor/nodeIncrementalSort.c"}, "parallel_callbacks": ["ExecIncrementalSortEstimate", "ExecIncrementalSortInitializeDSM", "ExecIncrementalSortInitializeWorker", "ExecIncrementalSortRetrieveInstrumentation"]}, "comparison": {"left": "12", "right": "13", "status": "added", "diff": "--- PostgreSQL 12\n+++ PostgreSQL 13\n@@ -1 +1,16 @@\n-\u8be5\u7248\u672a\u6536\u5f55\n+{\n+  \"initializer\": \"ExecInitIncrementalSort\",\n+  \"memory_mechanism\": \"tuplesort\",\n+  \"node_tag\": \"T_IncrementalSort\",\n+  \"parallel_callbacks\": [\n+    \"ExecIncrementalSortEstimate\",\n+    \"ExecIncrementalSortInitializeDSM\",\n+    \"ExecIncrementalSortInitializeWorker\",\n+    \"ExecIncrementalSortRetrieveInstrumentation\"\n+  ],\n+  \"partial_modes\": [],\n+  \"strategies\": [],\n+  \"text_names\": [\n+    \"Incremental Sort\"\n+  ]\n+}"}}