This is an automated email from the ASF dual-hosted git repository.
bobhan1 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris-website.git
The following commit(s) were added to refs/heads/master by this push:
new 6b3eead0ef4 [docs](topn) Document phase-2 File Cache no-write option
(#4033)
6b3eead0ef4 is described below
commit 6b3eead0ef498cec1d1e06d508da4436740a4161
Author: bobhan1 <[email protected]>
AuthorDate: Wed Aug 5 14:51:02 2026 +0800
[docs](topn) Document phase-2 File Cache no-write option (#4033)
## Versions
- [x] dev
- [x] 4.x
- [ ] 3.x
- [ ] 2.1 or older (not covered by version/language sync gate)
## Languages
- [x] Chinese
- [x] English
- [ ] Japanese candidate translation needed
## Docs Checklist
- [x] Checked by AI
- [ ] Test Cases Built
- [x] Updated required version and language counterparts, or explained
why not
- [x] If only one language changed, confirmed whether source/translation
counterparts need sync
## Summary
- document the `enable_topn_lazy_mat_phase2_no_write_file_cache` session
variable in the TOPN optimization guide
- explain full local hits versus remote-only cache-miss behavior
- clarify that the option applies only to TOPN lazy-materialization
phase 2 for Doris internal tables in storage-compute separation mode
- add a runnable SQL example, aggregate and per-BE Profile metrics,
verification guidance, caveats, and tuning recommendations
## Related changes
- apache/doris#65021
- apache/doris#66172
## Scope
Synchronize the current and 4.x TOPN optimization guides in Chinese,
English, and Japanese. Versions 3.x and 2.1 are intentionally out of
scope because the corresponding code change is available on master and
branch-4.0.
## Validation
- `git diff --check`
- `python3 scripts/check_md_links_single.py <file> --no-external` for
all six synchronized pages
- front matter JSON, Markdown fence, admonition balance, and
cross-version consistency checks
---
.../topn-optimization.md | 125 ++++++++++++++++++++-
.../topn-optimization.md | 125 ++++++++++++++++++++-
.../topn-optimization.md | 125 ++++++++++++++++++++-
.../topn-optimization.md | 116 ++++++++++++++++++-
.../topn-optimization.md | 116 ++++++++++++++++++-
.../topn-optimization.md | 125 ++++++++++++++++++++-
6 files changed, 710 insertions(+), 22 deletions(-)
diff --git
a/docs/query-acceleration/optimization-technology-principle/topn-optimization.md
b/docs/query-acceleration/optimization-technology-principle/topn-optimization.md
index ca3263149cf..6a8d0ecc127 100644
---
a/docs/query-acceleration/optimization-technology-principle/topn-optimization.md
+++
b/docs/query-acceleration/optimization-technology-principle/topn-optimization.md
@@ -2,8 +2,8 @@
{
"title": "TOPN Query Optimization: ORDER BY LIMIT Acceleration Principles
and Configuration",
"language": "en",
- "description": "How does Doris accelerate ORDER BY LIMIT queries? This
article explains TOPN optimization principles, applicable limitations, session
parameters, and execution plan inspection methods.",
- "keywords": ["Doris TOPN optimization", "ORDER BY LIMIT acceleration",
"topn_opt_limit_threshold", "two-phase read", "RuntimePredicate", "Zonemap
filtering"]
+ "description": "How does Doris accelerate ORDER BY LIMIT queries? This
article explains TOPN optimization principles, applicable limitations, session
parameters, execution plan inspection methods, and the phase-2 File Cache
policy for lazy materialization in storage-compute separation deployments.",
+ "keywords": ["Doris TOPN optimization", "ORDER BY LIMIT acceleration",
"topn_opt_limit_threshold", "enable_topn_lazy_mat_phase2_no_write_file_cache",
"two-phase read", "File Cache", "RuntimePredicate", "Zonemap filtering"]
}
---
@@ -53,13 +53,14 @@ SELECT * FROM tablex WHERE xxx ORDER BY c1, c2 ... LIMIT n
## Configuration Parameters
-The following three parameters are all session variables. You can set them for
a single SQL statement or globally.
+The following four parameters are all session variables. You can set them for
a single SQL statement or globally.
| Parameter | Default | Effect | Tuning Suggestion |
| :--- | :--- | :--- | :--- |
| `topn_opt_limit_threshold` | 1024 | TOPN optimization is enabled only when
LIMIT n is less than this value | Set to `0` to disable the entire TOPN
optimization |
| `enable_two_phase_read_opt` | true | Whether to enable Optimization 3
(two-phase lazy materialization) | Set to `false` to disable Optimization 3
alone |
| `topn_filter_ratio` | 0.5 | Ratio threshold of LIMIT n to total table data |
When the LIMIT count exceeds half of the table data, the filter is no longer
generated |
+| `enable_topn_lazy_mat_phase2_no_write_file_cache` | false | In
storage-compute separation mode, controls whether phase 2 of lazy
materialization for Doris internal tables skips cache writeback on a File Cache
miss | Enable it only when phase-2 reads have low reuse and are likely to
pollute the cache |
<!-- Knowledge type: operation -->
<!-- Applicable scenarios: verifying whether TOPN optimization is enabled -->
@@ -78,7 +79,7 @@ EXPLAIN <your_sql>;
- `TOPN OPT`: **Optimization 1** (dynamic range filtering) is enabled
- `SORT LIMIT` under `VOlapScanNode`: **Optimization 2** (key-prefix
short-circuit read) is enabled
-- `OPT TWO PHASE`: **Optimization 3** (two-phase lazy materialization) is
enabled
+- `MaterializeNode` (or `OPT TWO PHASE` in older execution plans):
**Optimization 3** (two-phase lazy materialization) is enabled
**Example**:
@@ -103,6 +104,116 @@ EXPLAIN <your_sql>;
pushAggOp=NONE
```
+<!-- Knowledge type: configuration + operation + troubleshooting -->
+<!-- Applicable scenarios: controlling File Cache writes during TOPN lazy
materialization phase 2 in clusters with storage-compute separation -->
+
+## Control File Cache Writes During Lazy Materialization Phase 2
+
+In a cluster with storage-compute separation, phase 2 of TOPN lazy
materialization reads the remaining columns by the row IDs selected in phase 1.
When a small number of result rows are scattered across many Segments, the
cache blocks populated by these sparse reads may see little reuse and displace
hot data. In this case, enable
`enable_topn_lazy_mat_phase2_no_write_file_cache` so that phase 2 reads cache
misses directly from remote storage without writing them back to File Cache.
+
+This variable does not change query results. It changes only how phase 2
handles File Cache misses:
+
+| Setting | Phase-2 Read Behavior |
+| :--- | :--- |
+| `false` (default) | Uses the regular read-through and writeback policy: on a
cache miss, Doris reads remote data and writes the data to File Cache |
+| `true` | Reads local cache only when cache blocks in the `DOWNLOADED` state
fully cover the current read range. If any part is uncached or still
downloading, Doris reads the entire current range from remote storage without
creating or writing cache blocks |
+
+Before enabling this variable, note the following boundaries:
+
+- It takes effect only in storage-compute separation mode and controls only
phase 2 of TOPN lazy materialization for Doris internal tables. It currently
does not control phase-2 reads for external tables.
+- It supports Doris internal tables both with and without row store enabled.
+- It neither removes existing cache entries nor changes cache writes made by
phase 1, other queries, or other operators. The query's total File Cache writes
may therefore still be greater than zero.
+- It has no additional effect when File Cache is disabled or when the
execution plan does not contain a `MaterializeNode`.
+
+### Basic Usage
+
+The following example requires a cluster with storage-compute separation, File
Cache enabled on the BEs, and a user that can create and drop tables and insert
and query data in the target database. First, create a Duplicate Key internal
table:
+
+```sql
+DROP TABLE IF EXISTS topn_file_cache_demo;
+
+CREATE TABLE topn_file_cache_demo (
+ id BIGINT NOT NULL,
+ event_time DATETIME NOT NULL,
+ payload VARCHAR(128) NOT NULL
+)
+ENGINE=OLAP
+DUPLICATE KEY(id)
+DISTRIBUTED BY HASH(id) BUCKETS 1
+PROPERTIES (
+ "replication_num" = "1",
+ "light_schema_change" = "true"
+);
+
+INSERT INTO topn_file_cache_demo VALUES
+ (1, '2026-01-01 10:00:00', 'alpha'),
+ (2, '2026-01-02 10:00:00', 'beta'),
+ (3, '2026-01-03 10:00:00', 'gamma');
+```
+
+Enable Profile and the phase-2 no-write policy, inspect the execution plan,
and run the query:
+
+```sql
+SET enable_profile = true;
+SET profile_level = 2;
+SET enable_sql_cache = false;
+SET enable_query_cache = false;
+SET enable_topn_lazy_mat_phase2_no_write_file_cache = true;
+
+EXPLAIN SELECT id, payload
+FROM topn_file_cache_demo
+ORDER BY event_time DESC
+LIMIT 2;
+
+SELECT id, payload
+FROM topn_file_cache_demo
+ORDER BY event_time DESC
+LIMIT 2;
+```
+
+The execution plan should contain a `MaterializeNode`. The query returns the
following result regardless of whether the variable is enabled:
+
+```text
++----+---------+
+| id | payload |
++----+---------+
+| 3 | gamma |
+| 2 | beta |
++----+---------+
+2 rows in set
+```
+
+To restore the default cache writeback behavior, run:
+
+```sql
+SET enable_topn_lazy_mat_phase2_no_write_file_cache = false;
+```
+
+### Verify the Cache Policy in Profile
+
+After setting `profile_level` to `2`, inspect the following phase-2-specific
metrics under the execution operator corresponding to `MaterializeNode` in
Query Profile:
+
+| Dimension | Aggregate Metrics | Meaning |
+| :--- | :--- | :--- |
+| Read scale | `TopNLazyMaterializationSecondPhaseRowsRead`,
`TopNLazyMaterializationSecondPhaseSegmentsRead` | Number of rows read and
Segments accessed in phase 2 |
+| Local cache reads | `TopNLazyMaterializationSecondPhaseLocalIOCount`,
`TopNLazyMaterializationSecondPhaseLocalIOBytes`,
`TopNLazyMaterializationSecondPhaseLocalIOTime` | Count, bytes, and time of
reads from File Cache |
+| Remote reads | `TopNLazyMaterializationSecondPhaseRemoteIOCount`,
`TopNLazyMaterializationSecondPhaseRemoteIOBytes`,
`TopNLazyMaterializationSecondPhaseRemoteIOTime` | Count, bytes, and time of
reads from remote storage |
+| Cache bypass | `TopNLazyMaterializationSecondPhaseSkipCacheIOCount` | Number
of remote reads that were not written to File Cache |
+| Cache writes | `TopNLazyMaterializationSecondPhaseWriteCacheBytes`,
`TopNLazyMaterializationSecondPhaseWriteCacheIOTime` | Bytes written to File
Cache and time spent writing them |
+
+When the no-write policy is enabled, use the following patterns to verify its
behavior:
+
+| Cache State | Expected Metric Pattern |
+| :--- | :--- |
+| The current read range is not fully cached | `RemoteIOCount`,
`RemoteIOBytes`, and `SkipCacheIOCount` are greater than 0, while
`WriteCacheBytes` is 0 |
+| The current read range is fully covered by downloaded cache blocks |
`LocalIOCount` and `LocalIOBytes` are greater than 0, while `RemoteIOCount`,
`RemoteIOBytes`, and `WriteCacheBytes` are 0 |
+
+Profile also provides per-BE metrics.
`TopNLazyMaterializationSecondPhasePerBackend` lists the BEs. The other metric
names add `PerBackend` after `SecondPhase`, for example,
`TopNLazyMaterializationSecondPhasePerBackendRowsRead` and
`TopNLazyMaterializationSecondPhasePerBackendWriteCacheBytes`. Array elements
correspond to the BE list by index and accumulate data from multiple phase-2
fetches within the same query.
+
+:::note
+`TopNLazyMaterializationSecondPhaseWriteCacheBytes` covers only phase 2 of
lazy materialization. If general File Cache metrics still report writes, first
determine whether they come from phase 1 or another operator. For information
about obtaining a Profile, see [Query Profile Analysis](../query-profile.md).
+:::
+
<!-- Knowledge type: operation -->
<!-- Applicable scenarios: evaluating the actual benefit of TOPN optimization
-->
@@ -210,6 +321,10 @@ Set `enable_two_phase_read_opt = false`.
Confirm that TOPN optimization is not enabled on the MOR table. For MOR
tables, use the MOW model or avoid triggering this optimization path.
+**Q5: Why does the query still write to File Cache after I enable the phase-2
no-write policy?**
+
+The policy controls only phase 2 of TOPN lazy materialization for Doris
internal tables. Phase 1, other operators, and external-table reads may still
write to File Cache. Use `TopNLazyMaterializationSecondPhaseWriteCacheBytes` to
determine whether phase 2 performed cache writes instead of relying on the
query's total write volume.
+
## Quick Reference for Related Parameters
| Desired Effect | Setting |
@@ -218,3 +333,5 @@ Confirm that TOPN optimization is not enabled on the MOR
table. For MOR tables,
| Disable only two-phase lazy materialization | `SET enable_two_phase_read_opt
= false;` |
| Relax the LIMIT upper bound to cover more queries | Increase
`topn_opt_limit_threshold` appropriately |
| Adjust the ratio threshold for generating the filter | Modify
`topn_filter_ratio` |
+| Do not write phase-2 cache misses back to File Cache | `SET
enable_topn_lazy_mat_phase2_no_write_file_cache = true;` |
+| Restore the default phase-2 cache writeback behavior | `SET
enable_topn_lazy_mat_phase2_no_write_file_cache = false;` |
diff --git
a/i18n/zh-CN/docusaurus-plugin-content-docs/current/query-acceleration/optimization-technology-principle/topn-optimization.md
b/i18n/zh-CN/docusaurus-plugin-content-docs/current/query-acceleration/optimization-technology-principle/topn-optimization.md
index 687a0d4d8d1..6d156dd39c5 100644
---
a/i18n/zh-CN/docusaurus-plugin-content-docs/current/query-acceleration/optimization-technology-principle/topn-optimization.md
+++
b/i18n/zh-CN/docusaurus-plugin-content-docs/current/query-acceleration/optimization-technology-principle/topn-optimization.md
@@ -2,8 +2,8 @@
{
"title": "TOPN 查询优化:ORDER BY LIMIT 加速原理与配置",
"language": "zh-CN",
- "description": "Doris 如何加速 ORDER BY LIMIT 查询?本文介绍 TOPN 优化原理、适用限制、Session
参数与执行计划检查方法。",
- "keywords": ["Doris TOPN 优化", "ORDER BY LIMIT 加速",
"topn_opt_limit_threshold", "两阶段读取", "RuntimePredicate", "Zonemap 过滤"]
+ "description": "Doris 如何加速 ORDER BY LIMIT 查询?本文介绍 TOPN 优化原理、适用限制、Session
参数、执行计划检查方法,以及存算分离场景下延迟物化第二阶段的 File Cache 策略。",
+ "keywords": ["Doris TOPN 优化", "ORDER BY LIMIT 加速",
"topn_opt_limit_threshold", "enable_topn_lazy_mat_phase2_no_write_file_cache",
"两阶段读取", "File Cache", "RuntimePredicate", "Zonemap 过滤"]
}
---
@@ -53,13 +53,14 @@ SELECT * FROM tablex WHERE xxx ORDER BY c1, c2 ... LIMIT n
## 配置参数
-以下三个参数均为 Session Variable,可针对单条 SQL 设置或全局设置。
+以下四个参数均为 Session Variable,可针对单条 SQL 设置或全局设置。
| 参数 | 默认值 | 作用 | 调优建议 |
| :--- | :--- | :--- | :--- |
| `topn_opt_limit_threshold` | 1024 | LIMIT n 小于该值才启用 TOPN 优化 | 设为 `0` 可关闭整个
TOPN 优化 |
| `enable_two_phase_read_opt` | true | 是否启用优化 3(两阶段延迟物化) | 设为 `false` 可单独关闭优化
3 |
| `topn_filter_ratio` | 0.5 | LIMIT n 与表总数据的比率阈值 | 当 LIMIT 数量超过表数据一半时不再生成
filter |
+| `enable_topn_lazy_mat_phase2_no_write_file_cache` | false | 在存算分离模式下,控制
Doris 内表的延迟物化第二阶段是否在 File Cache miss 时跳过缓存回写 | 仅在第二阶段读取的数据复用率低、容易污染缓存时开启 |
<!-- 知识类型:操作 -->
<!-- 适用场景:验证 TOPN 优化是否启用 -->
@@ -78,7 +79,7 @@ EXPLAIN <your_sql>;
- `TOPN OPT` —— 启用了 **优化 1**(动态范围过滤)
- `VOlapScanNode` 下出现 `SORT LIMIT` —— 启用了 **优化 2**(Key 前缀短路读取)
-- `OPT TWO PHASE` —— 启用了 **优化 3**(两阶段延迟物化)
+- `MaterializeNode`(或旧执行计划中的 `OPT TWO PHASE`)—— 启用了 **优化 3**(两阶段延迟物化)
**示例**:
@@ -103,6 +104,116 @@ EXPLAIN <your_sql>;
pushAggOp=NONE
```
+<!-- 知识类型:配置 + 操作 + 排查 -->
+<!-- 适用场景:存算分离集群控制 TOPN 延迟物化第二阶段的 File Cache 写入 -->
+
+## 控制延迟物化第二阶段的 File Cache 写入
+
+在存算分离集群中,TOPN 延迟物化的第二阶段会按第一阶段选出的行号读取其余列。若少量结果行分散在大量 Segment
中,这些离散读取填充的缓存块可能很少被再次访问,并挤占热点数据的缓存空间。此时可以开启
`enable_topn_lazy_mat_phase2_no_write_file_cache`,让第二阶段在缓存未命中时直接读取远端存储而不回写 File
Cache。
+
+该开关不改变查询结果,只改变第二阶段的 File Cache miss 处理方式:
+
+| 设置 | 第二阶段读取行为 |
+| :--- | :--- |
+| `false`(默认) | 沿用常规的读穿透与回写策略:缓存 miss 时读取远端数据,并将读取的数据写入 File Cache |
+| `true` | 仅当本次读取范围被状态为 `DOWNLOADED`
的缓存块完整覆盖时读取本地缓存;只要存在未缓存或尚未下载完成的范围,本次读取范围就直接从远端读取,且不创建或写入缓存块 |
+
+开启该开关时请注意以下边界:
+
+- 只在存算分离模式下生效,并且只控制 Doris 内表的 TOPN 延迟物化第二阶段;当前不控制外表的第二阶段读取。
+- 同时支持开启和未开启行存的 Doris 内表。
+- 不会清理已有缓存,也不会改变第一阶段、其他查询或其他算子的缓存写入行为。因此,整个查询的 File Cache 写入量仍可能大于 0。
+- 若 File Cache 未启用,或者执行计划中没有 `MaterializeNode`,该开关不会产生额外效果。
+
+### 基本使用
+
+以下示例要求使用存算分离集群,BE 已启用 File Cache,并使用具备建表、删表、写入和查询权限的用户执行。先创建一个 Duplicate Key
内表:
+
+```sql
+DROP TABLE IF EXISTS topn_file_cache_demo;
+
+CREATE TABLE topn_file_cache_demo (
+ id BIGINT NOT NULL,
+ event_time DATETIME NOT NULL,
+ payload VARCHAR(128) NOT NULL
+)
+ENGINE=OLAP
+DUPLICATE KEY(id)
+DISTRIBUTED BY HASH(id) BUCKETS 1
+PROPERTIES (
+ "replication_num" = "1",
+ "light_schema_change" = "true"
+);
+
+INSERT INTO topn_file_cache_demo VALUES
+ (1, '2026-01-01 10:00:00', 'alpha'),
+ (2, '2026-01-02 10:00:00', 'beta'),
+ (3, '2026-01-03 10:00:00', 'gamma');
+```
+
+开启 Profile 和第二阶段不回写策略,然后检查执行计划并执行查询:
+
+```sql
+SET enable_profile = true;
+SET profile_level = 2;
+SET enable_sql_cache = false;
+SET enable_query_cache = false;
+SET enable_topn_lazy_mat_phase2_no_write_file_cache = true;
+
+EXPLAIN SELECT id, payload
+FROM topn_file_cache_demo
+ORDER BY event_time DESC
+LIMIT 2;
+
+SELECT id, payload
+FROM topn_file_cache_demo
+ORDER BY event_time DESC
+LIMIT 2;
+```
+
+执行计划中应包含 `MaterializeNode`。查询结果如下;开关开启或关闭不会改变结果:
+
+```text
++----+---------+
+| id | payload |
++----+---------+
+| 3 | gamma |
+| 2 | beta |
++----+---------+
+2 rows in set
+```
+
+如需恢复默认的缓存回写行为,执行:
+
+```sql
+SET enable_topn_lazy_mat_phase2_no_write_file_cache = false;
+```
+
+### 通过 Profile 验证缓存策略
+
+将 `profile_level` 设为 `2` 后,在 Query Profile 的 `MaterializeNode`
对应执行算子中查看以下第二阶段专用指标:
+
+| 观测维度 | 聚合指标 | 含义 |
+| :--- | :--- | :--- |
+| 读取规模 |
`TopNLazyMaterializationSecondPhaseRowsRead`、`TopNLazyMaterializationSecondPhaseSegmentsRead`
| 第二阶段读取的行数和涉及的 Segment 数 |
+| 本地缓存读取 |
`TopNLazyMaterializationSecondPhaseLocalIOCount`、`TopNLazyMaterializationSecondPhaseLocalIOBytes`、`TopNLazyMaterializationSecondPhaseLocalIOTime`
| 从 File Cache 读取的次数、字节数和耗时 |
+| 远端读取 |
`TopNLazyMaterializationSecondPhaseRemoteIOCount`、`TopNLazyMaterializationSecondPhaseRemoteIOBytes`、`TopNLazyMaterializationSecondPhaseRemoteIOTime`
| 从远端存储读取的次数、字节数和耗时 |
+| 跳过缓存 | `TopNLazyMaterializationSecondPhaseSkipCacheIOCount` | 从远端读取但未写入 File
Cache 的次数 |
+| 缓存写入 |
`TopNLazyMaterializationSecondPhaseWriteCacheBytes`、`TopNLazyMaterializationSecondPhaseWriteCacheIOTime`
| 写入 File Cache 的字节数和耗时 |
+
+开启不回写策略后,可以按以下特征确认行为:
+
+| 缓存状态 | 预期指标特征 |
+| :--- | :--- |
+| 本次读取范围未被完整缓存 | `RemoteIOCount`、`RemoteIOBytes` 和 `SkipCacheIOCount` 大于
0,`WriteCacheBytes` 为 0 |
+| 本次读取范围被已下载缓存块完整覆盖 | `LocalIOCount` 和 `LocalIOBytes` 大于
0,`RemoteIOCount`、`RemoteIOBytes` 和 `WriteCacheBytes` 为 0 |
+
+Profile 还提供分 BE 指标。`TopNLazyMaterializationSecondPhasePerBackend` 列出
BE,其他指标在聚合指标名称的 `SecondPhase` 后增加 `PerBackend`,例如
`TopNLazyMaterializationSecondPhasePerBackendRowsRead` 和
`TopNLazyMaterializationSecondPhasePerBackendWriteCacheBytes`。各数组按下标与 BE
列表一一对应,并会累计同一查询中多次第二阶段 Fetch 的数据。
+
+:::note
+`TopNLazyMaterializationSecondPhaseWriteCacheBytes` 只统计延迟物化第二阶段。若通用 File Cache
指标仍显示写入,请先判断写入是否来自第一阶段或其他算子。有关 Profile 的获取方法,参见 [Query Profile
分析](../query-profile.md)。
+:::
+
<!-- 知识类型:操作 -->
<!-- 适用场景:评估 TOPN 优化的实际收益 -->
@@ -210,6 +321,10 @@ EXPLAIN <your_sql>;
确认未在 MOR 表上启用 TOPN 优化。MOR 表请使用 MOW 模型或避免触发该优化路径。
+**Q5:开启第二阶段不回写策略后,为什么查询仍有 File Cache 写入?**
+
+该策略只控制 Doris 内表的 TOPN 延迟物化第二阶段。第一阶段、其他算子和外表读取仍可能写入 File Cache。请使用
`TopNLazyMaterializationSecondPhaseWriteCacheBytes`
判断第二阶段是否发生写入,不要使用整个查询的写入量代替该指标。
+
## 相关参数对照速查
| 想要的效果 | 设置方式 |
@@ -218,3 +333,5 @@ EXPLAIN <your_sql>;
| 仅关闭两阶段延迟物化 | `SET enable_two_phase_read_opt = false;` |
| 放宽 LIMIT 上限以覆盖更多查询 | 适当增大 `topn_opt_limit_threshold` |
| 调整生成 filter 的比率阈值 | 修改 `topn_filter_ratio` |
+| 第二阶段缓存 miss 时不回写 File Cache | `SET
enable_topn_lazy_mat_phase2_no_write_file_cache = true;` |
+| 恢复第二阶段默认的缓存回写行为 | `SET enable_topn_lazy_mat_phase2_no_write_file_cache =
false;` |
diff --git
a/i18n/zh-CN/docusaurus-plugin-content-docs/version-4.x/query-acceleration/optimization-technology-principle/topn-optimization.md
b/i18n/zh-CN/docusaurus-plugin-content-docs/version-4.x/query-acceleration/optimization-technology-principle/topn-optimization.md
index 687a0d4d8d1..6d156dd39c5 100644
---
a/i18n/zh-CN/docusaurus-plugin-content-docs/version-4.x/query-acceleration/optimization-technology-principle/topn-optimization.md
+++
b/i18n/zh-CN/docusaurus-plugin-content-docs/version-4.x/query-acceleration/optimization-technology-principle/topn-optimization.md
@@ -2,8 +2,8 @@
{
"title": "TOPN 查询优化:ORDER BY LIMIT 加速原理与配置",
"language": "zh-CN",
- "description": "Doris 如何加速 ORDER BY LIMIT 查询?本文介绍 TOPN 优化原理、适用限制、Session
参数与执行计划检查方法。",
- "keywords": ["Doris TOPN 优化", "ORDER BY LIMIT 加速",
"topn_opt_limit_threshold", "两阶段读取", "RuntimePredicate", "Zonemap 过滤"]
+ "description": "Doris 如何加速 ORDER BY LIMIT 查询?本文介绍 TOPN 优化原理、适用限制、Session
参数、执行计划检查方法,以及存算分离场景下延迟物化第二阶段的 File Cache 策略。",
+ "keywords": ["Doris TOPN 优化", "ORDER BY LIMIT 加速",
"topn_opt_limit_threshold", "enable_topn_lazy_mat_phase2_no_write_file_cache",
"两阶段读取", "File Cache", "RuntimePredicate", "Zonemap 过滤"]
}
---
@@ -53,13 +53,14 @@ SELECT * FROM tablex WHERE xxx ORDER BY c1, c2 ... LIMIT n
## 配置参数
-以下三个参数均为 Session Variable,可针对单条 SQL 设置或全局设置。
+以下四个参数均为 Session Variable,可针对单条 SQL 设置或全局设置。
| 参数 | 默认值 | 作用 | 调优建议 |
| :--- | :--- | :--- | :--- |
| `topn_opt_limit_threshold` | 1024 | LIMIT n 小于该值才启用 TOPN 优化 | 设为 `0` 可关闭整个
TOPN 优化 |
| `enable_two_phase_read_opt` | true | 是否启用优化 3(两阶段延迟物化) | 设为 `false` 可单独关闭优化
3 |
| `topn_filter_ratio` | 0.5 | LIMIT n 与表总数据的比率阈值 | 当 LIMIT 数量超过表数据一半时不再生成
filter |
+| `enable_topn_lazy_mat_phase2_no_write_file_cache` | false | 在存算分离模式下,控制
Doris 内表的延迟物化第二阶段是否在 File Cache miss 时跳过缓存回写 | 仅在第二阶段读取的数据复用率低、容易污染缓存时开启 |
<!-- 知识类型:操作 -->
<!-- 适用场景:验证 TOPN 优化是否启用 -->
@@ -78,7 +79,7 @@ EXPLAIN <your_sql>;
- `TOPN OPT` —— 启用了 **优化 1**(动态范围过滤)
- `VOlapScanNode` 下出现 `SORT LIMIT` —— 启用了 **优化 2**(Key 前缀短路读取)
-- `OPT TWO PHASE` —— 启用了 **优化 3**(两阶段延迟物化)
+- `MaterializeNode`(或旧执行计划中的 `OPT TWO PHASE`)—— 启用了 **优化 3**(两阶段延迟物化)
**示例**:
@@ -103,6 +104,116 @@ EXPLAIN <your_sql>;
pushAggOp=NONE
```
+<!-- 知识类型:配置 + 操作 + 排查 -->
+<!-- 适用场景:存算分离集群控制 TOPN 延迟物化第二阶段的 File Cache 写入 -->
+
+## 控制延迟物化第二阶段的 File Cache 写入
+
+在存算分离集群中,TOPN 延迟物化的第二阶段会按第一阶段选出的行号读取其余列。若少量结果行分散在大量 Segment
中,这些离散读取填充的缓存块可能很少被再次访问,并挤占热点数据的缓存空间。此时可以开启
`enable_topn_lazy_mat_phase2_no_write_file_cache`,让第二阶段在缓存未命中时直接读取远端存储而不回写 File
Cache。
+
+该开关不改变查询结果,只改变第二阶段的 File Cache miss 处理方式:
+
+| 设置 | 第二阶段读取行为 |
+| :--- | :--- |
+| `false`(默认) | 沿用常规的读穿透与回写策略:缓存 miss 时读取远端数据,并将读取的数据写入 File Cache |
+| `true` | 仅当本次读取范围被状态为 `DOWNLOADED`
的缓存块完整覆盖时读取本地缓存;只要存在未缓存或尚未下载完成的范围,本次读取范围就直接从远端读取,且不创建或写入缓存块 |
+
+开启该开关时请注意以下边界:
+
+- 只在存算分离模式下生效,并且只控制 Doris 内表的 TOPN 延迟物化第二阶段;当前不控制外表的第二阶段读取。
+- 同时支持开启和未开启行存的 Doris 内表。
+- 不会清理已有缓存,也不会改变第一阶段、其他查询或其他算子的缓存写入行为。因此,整个查询的 File Cache 写入量仍可能大于 0。
+- 若 File Cache 未启用,或者执行计划中没有 `MaterializeNode`,该开关不会产生额外效果。
+
+### 基本使用
+
+以下示例要求使用存算分离集群,BE 已启用 File Cache,并使用具备建表、删表、写入和查询权限的用户执行。先创建一个 Duplicate Key
内表:
+
+```sql
+DROP TABLE IF EXISTS topn_file_cache_demo;
+
+CREATE TABLE topn_file_cache_demo (
+ id BIGINT NOT NULL,
+ event_time DATETIME NOT NULL,
+ payload VARCHAR(128) NOT NULL
+)
+ENGINE=OLAP
+DUPLICATE KEY(id)
+DISTRIBUTED BY HASH(id) BUCKETS 1
+PROPERTIES (
+ "replication_num" = "1",
+ "light_schema_change" = "true"
+);
+
+INSERT INTO topn_file_cache_demo VALUES
+ (1, '2026-01-01 10:00:00', 'alpha'),
+ (2, '2026-01-02 10:00:00', 'beta'),
+ (3, '2026-01-03 10:00:00', 'gamma');
+```
+
+开启 Profile 和第二阶段不回写策略,然后检查执行计划并执行查询:
+
+```sql
+SET enable_profile = true;
+SET profile_level = 2;
+SET enable_sql_cache = false;
+SET enable_query_cache = false;
+SET enable_topn_lazy_mat_phase2_no_write_file_cache = true;
+
+EXPLAIN SELECT id, payload
+FROM topn_file_cache_demo
+ORDER BY event_time DESC
+LIMIT 2;
+
+SELECT id, payload
+FROM topn_file_cache_demo
+ORDER BY event_time DESC
+LIMIT 2;
+```
+
+执行计划中应包含 `MaterializeNode`。查询结果如下;开关开启或关闭不会改变结果:
+
+```text
++----+---------+
+| id | payload |
++----+---------+
+| 3 | gamma |
+| 2 | beta |
++----+---------+
+2 rows in set
+```
+
+如需恢复默认的缓存回写行为,执行:
+
+```sql
+SET enable_topn_lazy_mat_phase2_no_write_file_cache = false;
+```
+
+### 通过 Profile 验证缓存策略
+
+将 `profile_level` 设为 `2` 后,在 Query Profile 的 `MaterializeNode`
对应执行算子中查看以下第二阶段专用指标:
+
+| 观测维度 | 聚合指标 | 含义 |
+| :--- | :--- | :--- |
+| 读取规模 |
`TopNLazyMaterializationSecondPhaseRowsRead`、`TopNLazyMaterializationSecondPhaseSegmentsRead`
| 第二阶段读取的行数和涉及的 Segment 数 |
+| 本地缓存读取 |
`TopNLazyMaterializationSecondPhaseLocalIOCount`、`TopNLazyMaterializationSecondPhaseLocalIOBytes`、`TopNLazyMaterializationSecondPhaseLocalIOTime`
| 从 File Cache 读取的次数、字节数和耗时 |
+| 远端读取 |
`TopNLazyMaterializationSecondPhaseRemoteIOCount`、`TopNLazyMaterializationSecondPhaseRemoteIOBytes`、`TopNLazyMaterializationSecondPhaseRemoteIOTime`
| 从远端存储读取的次数、字节数和耗时 |
+| 跳过缓存 | `TopNLazyMaterializationSecondPhaseSkipCacheIOCount` | 从远端读取但未写入 File
Cache 的次数 |
+| 缓存写入 |
`TopNLazyMaterializationSecondPhaseWriteCacheBytes`、`TopNLazyMaterializationSecondPhaseWriteCacheIOTime`
| 写入 File Cache 的字节数和耗时 |
+
+开启不回写策略后,可以按以下特征确认行为:
+
+| 缓存状态 | 预期指标特征 |
+| :--- | :--- |
+| 本次读取范围未被完整缓存 | `RemoteIOCount`、`RemoteIOBytes` 和 `SkipCacheIOCount` 大于
0,`WriteCacheBytes` 为 0 |
+| 本次读取范围被已下载缓存块完整覆盖 | `LocalIOCount` 和 `LocalIOBytes` 大于
0,`RemoteIOCount`、`RemoteIOBytes` 和 `WriteCacheBytes` 为 0 |
+
+Profile 还提供分 BE 指标。`TopNLazyMaterializationSecondPhasePerBackend` 列出
BE,其他指标在聚合指标名称的 `SecondPhase` 后增加 `PerBackend`,例如
`TopNLazyMaterializationSecondPhasePerBackendRowsRead` 和
`TopNLazyMaterializationSecondPhasePerBackendWriteCacheBytes`。各数组按下标与 BE
列表一一对应,并会累计同一查询中多次第二阶段 Fetch 的数据。
+
+:::note
+`TopNLazyMaterializationSecondPhaseWriteCacheBytes` 只统计延迟物化第二阶段。若通用 File Cache
指标仍显示写入,请先判断写入是否来自第一阶段或其他算子。有关 Profile 的获取方法,参见 [Query Profile
分析](../query-profile.md)。
+:::
+
<!-- 知识类型:操作 -->
<!-- 适用场景:评估 TOPN 优化的实际收益 -->
@@ -210,6 +321,10 @@ EXPLAIN <your_sql>;
确认未在 MOR 表上启用 TOPN 优化。MOR 表请使用 MOW 模型或避免触发该优化路径。
+**Q5:开启第二阶段不回写策略后,为什么查询仍有 File Cache 写入?**
+
+该策略只控制 Doris 内表的 TOPN 延迟物化第二阶段。第一阶段、其他算子和外表读取仍可能写入 File Cache。请使用
`TopNLazyMaterializationSecondPhaseWriteCacheBytes`
判断第二阶段是否发生写入,不要使用整个查询的写入量代替该指标。
+
## 相关参数对照速查
| 想要的效果 | 设置方式 |
@@ -218,3 +333,5 @@ EXPLAIN <your_sql>;
| 仅关闭两阶段延迟物化 | `SET enable_two_phase_read_opt = false;` |
| 放宽 LIMIT 上限以覆盖更多查询 | 适当增大 `topn_opt_limit_threshold` |
| 调整生成 filter 的比率阈值 | 修改 `topn_filter_ratio` |
+| 第二阶段缓存 miss 时不回写 File Cache | `SET
enable_topn_lazy_mat_phase2_no_write_file_cache = true;` |
+| 恢复第二阶段默认的缓存回写行为 | `SET enable_topn_lazy_mat_phase2_no_write_file_cache =
false;` |
diff --git
a/ja-source/docusaurus-plugin-content-docs/current/query-acceleration/optimization-technology-principle/topn-optimization.md
b/ja-source/docusaurus-plugin-content-docs/current/query-acceleration/optimization-technology-principle/topn-optimization.md
index 1c8ab801546..27e00dda17a 100644
---
a/ja-source/docusaurus-plugin-content-docs/current/query-acceleration/optimization-technology-principle/topn-optimization.md
+++
b/ja-source/docusaurus-plugin-content-docs/current/query-acceleration/optimization-technology-principle/topn-optimization.md
@@ -2,7 +2,7 @@
{
"title": "TOPNクエリ最適化",
"language": "ja",
- "description": "TOPN クエリとは、ORDER BY LIMIT
操作を含むクエリを指し、ログ検索やその他の詳細なクエリシナリオで一般的に使用されます。"
+ "description": "TOPN クエリとは、ORDER BY LIMIT
操作を含むクエリを指し、ログ検索やその他の詳細なクエリシナリオで一般的に使用されます。本ページでは、TOPN最適化の仕組み、設定、およびストレージ・コンピュート分離環境における遅延マテリアライゼーション第2フェーズのFile
Cacheポリシーを説明します。"
}
---
TOPN クエリは、ORDER BY LIMIT 操作を含むクエリを指し、ログ検索やその他の詳細なクエリシナリオで一般的です。Doris
はこのタイプのクエリを自動的に最適化します。
@@ -26,7 +26,7 @@ SELECT * FROM tablex WHERE xxx ORDER BY c1,c2 ... LIMIT n
## 設定とクエリ分析
-以下の2つのパラメータは、特定のSQLまたはグローバルに設定できるセッション変数です。
+以下の4つのパラメータは、特定のSQLまたはグローバルに設定できるセッション変数です。
1.
`topn_opt_limit_threshold`:このセッション変数は、TOPN最適化を適用するかどうかを決定します。デフォルトは1024で、0に設定すると最適化が無効になります。
@@ -34,6 +34,8 @@ SELECT * FROM tablex WHERE xxx ORDER BY c1,c2 ... LIMIT n
3. `topn_filter_ratio`、LIMIT
nとテーブル内の総データとの比率で、デフォルト値は0.5です。これは、LIMITの数がテーブル内のデータの半分を超える場合、フィルタが生成されないことを意味します。
+4.
`enable_topn_lazy_mat_phase2_no_write_file_cache`:ストレージ・コンピュート分離モードで、Doris内部テーブルのTOPN遅延マテリアライゼーション第2フェーズがFile
Cacheミス時にキャッシュへの書き戻しをスキップするかを制御します。デフォルトはfalseです。
+
### TOPNクエリ最適化が有効かどうかの確認
特定のSQLに対してTOPNクエリ最適化が有効かどうかを確認するには、`EXPLAIN`文を使用してクエリプランを取得できます。例は以下の通りです:
@@ -42,7 +44,7 @@ SELECT * FROM tablex WHERE xxx ORDER BY c1,c2 ... LIMIT n
- `SORT LIMIT`付きの`VOlapScanNode`は最適化ポイント2が適用されていることを示します。
-- `OPT TWO PHASE`は最適化ポイント3が適用されていることを示します。
+- `MaterializeNode`(または旧実行プランの`OPT TWO PHASE`)は最適化ポイント3が適用されていることを示します。
```sql
1:VTOP-N(137)
@@ -64,6 +66,114 @@ SELECT * FROM tablex WHERE xxx ORDER BY c1,c2 ... LIMIT n
cardinality=345472780, avgRowSize=0.0, numNodes=1
pushAggOp=NONE
```
+
+## 遅延マテリアライゼーション第2フェーズのFile Cache書き込みを制御する
+
+ストレージ・コンピュート分離クラスタでは、TOPN遅延マテリアライゼーションの第2フェーズが、第1フェーズで選択した行IDを使って残りの列を読み取ります。少数の結果行が多数のSegmentに分散している場合、このような離散読み取りによって格納されたキャッシュブロックは再利用されにくく、ホットデータを追い出す可能性があります。この場合は`enable_topn_lazy_mat_phase2_no_write_file_cache`を有効にすると、第2フェーズはFile
Cacheミスをリモートストレージから直接読み取り、File Cacheへ書き戻しません。
+
+この変数はクエリ結果を変更せず、第2フェーズでFile Cacheミスが発生したときの処理だけを変更します。
+
+| 設定 | 第2フェーズの読み取り動作 |
+| :--- | :--- |
+| `false`(デフォルト) | 通常のリードスルーおよび書き戻しポリシーを使用します。キャッシュミス時にリモートデータを読み取り、そのデータをFile
Cacheへ書き込みます |
+| `true` |
`DOWNLOADED`状態のキャッシュブロックが今回の読み取り範囲全体をカバーしている場合のみ、ローカルキャッシュから読み取ります。未キャッシュまたはダウンロード中の範囲が一部でもある場合は、今回の読み取り範囲全体をリモートストレージから読み取り、キャッシュブロックを作成または書き込みません
|
+
+この変数を有効にする前に、次の適用範囲を確認してください。
+
+-
ストレージ・コンピュート分離モードでのみ有効で、Doris内部テーブルのTOPN遅延マテリアライゼーション第2フェーズだけを制御します。現時点では、外部テーブルの第2フェーズ読み取りは制御しません。
+- 行ストアの有効・無効にかかわらず、Doris内部テーブルをサポートします。
+- 既存のキャッシュを削除せず、第1フェーズ、他のクエリ、他のオペレータによるキャッシュ書き込みも変更しません。このため、クエリ全体のFile
Cache書き込み量が0より大きい場合があります。
+- File Cacheが無効な場合、または実行プランに`MaterializeNode`がない場合は、追加の効果はありません。
+
+### 基本的な使用方法
+
+次の例では、ストレージ・コンピュート分離クラスタを使用し、BEでFile
Cacheが有効になっている必要があります。また、対象データベースでテーブルの作成と削除、およびデータの書き込みとクエリを実行できるユーザーで実行してください。まず、Duplicate
Keyの内部テーブルを作成します。
+
+```sql
+DROP TABLE IF EXISTS topn_file_cache_demo;
+
+CREATE TABLE topn_file_cache_demo (
+ id BIGINT NOT NULL,
+ event_time DATETIME NOT NULL,
+ payload VARCHAR(128) NOT NULL
+)
+ENGINE=OLAP
+DUPLICATE KEY(id)
+DISTRIBUTED BY HASH(id) BUCKETS 1
+PROPERTIES (
+ "replication_num" = "1",
+ "light_schema_change" = "true"
+);
+
+INSERT INTO topn_file_cache_demo VALUES
+ (1, '2026-01-01 10:00:00', 'alpha'),
+ (2, '2026-01-02 10:00:00', 'beta'),
+ (3, '2026-01-03 10:00:00', 'gamma');
+```
+
+Profileと第2フェーズの書き戻し抑制ポリシーを有効にし、実行プランを確認してクエリを実行します。
+
+```sql
+SET enable_profile = true;
+SET profile_level = 2;
+SET enable_sql_cache = false;
+SET enable_query_cache = false;
+SET enable_topn_lazy_mat_phase2_no_write_file_cache = true;
+
+EXPLAIN SELECT id, payload
+FROM topn_file_cache_demo
+ORDER BY event_time DESC
+LIMIT 2;
+
+SELECT id, payload
+FROM topn_file_cache_demo
+ORDER BY event_time DESC
+LIMIT 2;
+```
+
+実行プランには`MaterializeNode`が含まれている必要があります。変数の有効・無効にかかわらず、クエリ結果は次のようになります。
+
+```text
++----+---------+
+| id | payload |
++----+---------+
+| 3 | gamma |
+| 2 | beta |
++----+---------+
+2 rows in set
+```
+
+デフォルトのキャッシュ書き戻し動作へ戻すには、次を実行します。
+
+```sql
+SET enable_topn_lazy_mat_phase2_no_write_file_cache = false;
+```
+
+### Profileでキャッシュポリシーを確認する
+
+`profile_level`を`2`に設定した後、Query
Profileの`MaterializeNode`に対応する実行オペレータで、次の第2フェーズ専用メトリクスを確認します。
+
+| 観測項目 | 集約メトリクス | 意味 |
+| :--- | :--- | :--- |
+| 読み取り規模 |
`TopNLazyMaterializationSecondPhaseRowsRead`、`TopNLazyMaterializationSecondPhaseSegmentsRead`
| 第2フェーズで読み取った行数とアクセスしたSegment数 |
+| ローカルキャッシュ読み取り |
`TopNLazyMaterializationSecondPhaseLocalIOCount`、`TopNLazyMaterializationSecondPhaseLocalIOBytes`、`TopNLazyMaterializationSecondPhaseLocalIOTime`
| File Cacheから読み取った回数、バイト数、所要時間 |
+| リモート読み取り |
`TopNLazyMaterializationSecondPhaseRemoteIOCount`、`TopNLazyMaterializationSecondPhaseRemoteIOBytes`、`TopNLazyMaterializationSecondPhaseRemoteIOTime`
| リモートストレージから読み取った回数、バイト数、所要時間 |
+| キャッシュのスキップ | `TopNLazyMaterializationSecondPhaseSkipCacheIOCount` |
リモートから読み取り、File Cacheへ書き込まなかった回数 |
+| キャッシュ書き込み |
`TopNLazyMaterializationSecondPhaseWriteCacheBytes`、`TopNLazyMaterializationSecondPhaseWriteCacheIOTime`
| File Cacheへ書き込んだバイト数と所要時間 |
+
+書き戻し抑制ポリシーを有効にした場合は、次のパターンで動作を確認できます。
+
+| キャッシュ状態 | 期待されるメトリクス |
+| :--- | :--- |
+| 今回の読み取り範囲が完全にはキャッシュされていない |
`RemoteIOCount`、`RemoteIOBytes`、`SkipCacheIOCount`が0より大きく、`WriteCacheBytes`は0 |
+| 今回の読み取り範囲全体がダウンロード済みキャッシュブロックでカバーされている |
`LocalIOCount`と`LocalIOBytes`が0より大きく、`RemoteIOCount`、`RemoteIOBytes`、`WriteCacheBytes`は0
|
+
+ProfileにはBE別メトリクスもあります。`TopNLazyMaterializationSecondPhasePerBackend`にはBEの一覧が表示され、他のメトリクス名には`SecondPhase`の後に`PerBackend`が追加されます。たとえば、`TopNLazyMaterializationSecondPhasePerBackendRowsRead`と`TopNLazyMaterializationSecondPhasePerBackendWriteCacheBytes`です。各配列要素はインデックスによってBE一覧と対応し、同じクエリ内で複数回実行された第2フェーズFetchのデータを累積します。
+
+:::note
+`TopNLazyMaterializationSecondPhaseWriteCacheBytes`は遅延マテリアライゼーション第2フェーズだけを集計します。一般的なFile
Cacheメトリクスに書き込みが残っている場合は、まず第1フェーズまたは他のオペレータによる書き込みかどうかを確認してください。Profileの取得方法については、[Query
Profile分析](../query-profile.md)を参照してください。
+:::
+
### 実行中のTOPNクエリ最適化の効果を確認する
まず、`topn_opt_limit_threshold`を0に設定してTOPNクエリ最適化を無効にし、最適化を有効にした場合と無効にした場合のSQLの実行時間を比較します。
diff --git
a/ja-source/docusaurus-plugin-content-docs/version-4.x/query-acceleration/optimization-technology-principle/topn-optimization.md
b/ja-source/docusaurus-plugin-content-docs/version-4.x/query-acceleration/optimization-technology-principle/topn-optimization.md
index 9f84e2733a4..0081731102e 100644
---
a/ja-source/docusaurus-plugin-content-docs/version-4.x/query-acceleration/optimization-technology-principle/topn-optimization.md
+++
b/ja-source/docusaurus-plugin-content-docs/version-4.x/query-acceleration/optimization-technology-principle/topn-optimization.md
@@ -1,7 +1,7 @@
---
{
"title": "TOPN クエリの最適化",
- "description": "TOPN クエリは、ORDER BY LIMIT
操作を含むクエリを指し、ログ検索やその他の詳細なクエリシナリオで一般的に使用されます。",
+ "description": "TOPN クエリは、ORDER BY LIMIT
操作を含むクエリを指し、ログ検索やその他の詳細なクエリシナリオで一般的に使用されます。本ページでは、TOPN最適化の仕組み、設定、およびストレージ・コンピュート分離環境における遅延マテリアライゼーション第2フェーズのFile
Cacheポリシーを説明します。",
"language": "ja"
}
---
@@ -26,7 +26,7 @@ SELECT * FROM tablex WHERE xxx ORDER BY c1,c2 ... LIMIT n
## 設定とクエリ解析
-以下の2つのパラメータは、特定のSQLまたはグローバルに設定できるセッション変数です。
+以下の4つのパラメータは、特定のSQLまたはグローバルに設定できるセッション変数です。
1.
`topn_opt_limit_threshold`:このセッション変数は、TOPN最適化が適用されるかどうかを決定します。デフォルトは1024で、0に設定すると最適化が無効になります。
@@ -34,6 +34,8 @@ SELECT * FROM tablex WHERE xxx ORDER BY c1,c2 ... LIMIT n
3. `topn_filter_ratio`:LIMIT
nとTable内の総データの比率で、デフォルト値は0.5です。これは、LIMITの数がTable内のデータの半分を超える場合、フィルタが生成されないことを意味します。
+4.
`enable_topn_lazy_mat_phase2_no_write_file_cache`:ストレージ・コンピュート分離モードで、Doris内部テーブルのTOPN遅延マテリアライゼーション第2フェーズがFile
Cacheミス時にキャッシュへの書き戻しをスキップするかを制御します。デフォルトはfalseです。
+
### TOPNクエリ最適化が有効かどうかの確認
特定のSQLに対してTOPNクエリ最適化が有効になっているかを確認するには、`EXPLAIN`文を使用してクエリプランを取得できます。例は以下の通りです:
@@ -42,7 +44,7 @@ SELECT * FROM tablex WHERE xxx ORDER BY c1,c2 ... LIMIT n
- `SORT LIMIT`を持つ`VOlapScanNode`は、最適化ポイント2が適用されていることを示します。
-- `OPT TWO PHASE`は、最適化ポイント3が適用されていることを示します。
+- `MaterializeNode`(または旧実行プランの`OPT TWO PHASE`)は、最適化ポイント3が適用されていることを示します。
```sql
1:VTOP-N(137)
@@ -64,6 +66,114 @@ SELECT * FROM tablex WHERE xxx ORDER BY c1,c2 ... LIMIT n
cardinality=345472780, avgRowSize=0.0, numNodes=1
pushAggOp=NONE
```
+
+## 遅延マテリアライゼーション第2フェーズのFile Cache書き込みを制御する
+
+ストレージ・コンピュート分離クラスタでは、TOPN遅延マテリアライゼーションの第2フェーズが、第1フェーズで選択した行IDを使って残りの列を読み取ります。少数の結果行が多数のSegmentに分散している場合、このような離散読み取りによって格納されたキャッシュブロックは再利用されにくく、ホットデータを追い出す可能性があります。この場合は`enable_topn_lazy_mat_phase2_no_write_file_cache`を有効にすると、第2フェーズはFile
Cacheミスをリモートストレージから直接読み取り、File Cacheへ書き戻しません。
+
+この変数はクエリ結果を変更せず、第2フェーズでFile Cacheミスが発生したときの処理だけを変更します。
+
+| 設定 | 第2フェーズの読み取り動作 |
+| :--- | :--- |
+| `false`(デフォルト) | 通常のリードスルーおよび書き戻しポリシーを使用します。キャッシュミス時にリモートデータを読み取り、そのデータをFile
Cacheへ書き込みます |
+| `true` |
`DOWNLOADED`状態のキャッシュブロックが今回の読み取り範囲全体をカバーしている場合のみ、ローカルキャッシュから読み取ります。未キャッシュまたはダウンロード中の範囲が一部でもある場合は、今回の読み取り範囲全体をリモートストレージから読み取り、キャッシュブロックを作成または書き込みません
|
+
+この変数を有効にする前に、次の適用範囲を確認してください。
+
+-
ストレージ・コンピュート分離モードでのみ有効で、Doris内部テーブルのTOPN遅延マテリアライゼーション第2フェーズだけを制御します。現時点では、外部テーブルの第2フェーズ読み取りは制御しません。
+- 行ストアの有効・無効にかかわらず、Doris内部テーブルをサポートします。
+- 既存のキャッシュを削除せず、第1フェーズ、他のクエリ、他のオペレータによるキャッシュ書き込みも変更しません。このため、クエリ全体のFile
Cache書き込み量が0より大きい場合があります。
+- File Cacheが無効な場合、または実行プランに`MaterializeNode`がない場合は、追加の効果はありません。
+
+### 基本的な使用方法
+
+次の例では、ストレージ・コンピュート分離クラスタを使用し、BEでFile
Cacheが有効になっている必要があります。また、対象データベースでテーブルの作成と削除、およびデータの書き込みとクエリを実行できるユーザーで実行してください。まず、Duplicate
Keyの内部テーブルを作成します。
+
+```sql
+DROP TABLE IF EXISTS topn_file_cache_demo;
+
+CREATE TABLE topn_file_cache_demo (
+ id BIGINT NOT NULL,
+ event_time DATETIME NOT NULL,
+ payload VARCHAR(128) NOT NULL
+)
+ENGINE=OLAP
+DUPLICATE KEY(id)
+DISTRIBUTED BY HASH(id) BUCKETS 1
+PROPERTIES (
+ "replication_num" = "1",
+ "light_schema_change" = "true"
+);
+
+INSERT INTO topn_file_cache_demo VALUES
+ (1, '2026-01-01 10:00:00', 'alpha'),
+ (2, '2026-01-02 10:00:00', 'beta'),
+ (3, '2026-01-03 10:00:00', 'gamma');
+```
+
+Profileと第2フェーズの書き戻し抑制ポリシーを有効にし、実行プランを確認してクエリを実行します。
+
+```sql
+SET enable_profile = true;
+SET profile_level = 2;
+SET enable_sql_cache = false;
+SET enable_query_cache = false;
+SET enable_topn_lazy_mat_phase2_no_write_file_cache = true;
+
+EXPLAIN SELECT id, payload
+FROM topn_file_cache_demo
+ORDER BY event_time DESC
+LIMIT 2;
+
+SELECT id, payload
+FROM topn_file_cache_demo
+ORDER BY event_time DESC
+LIMIT 2;
+```
+
+実行プランには`MaterializeNode`が含まれている必要があります。変数の有効・無効にかかわらず、クエリ結果は次のようになります。
+
+```text
++----+---------+
+| id | payload |
++----+---------+
+| 3 | gamma |
+| 2 | beta |
++----+---------+
+2 rows in set
+```
+
+デフォルトのキャッシュ書き戻し動作へ戻すには、次を実行します。
+
+```sql
+SET enable_topn_lazy_mat_phase2_no_write_file_cache = false;
+```
+
+### Profileでキャッシュポリシーを確認する
+
+`profile_level`を`2`に設定した後、Query
Profileの`MaterializeNode`に対応する実行オペレータで、次の第2フェーズ専用メトリクスを確認します。
+
+| 観測項目 | 集約メトリクス | 意味 |
+| :--- | :--- | :--- |
+| 読み取り規模 |
`TopNLazyMaterializationSecondPhaseRowsRead`、`TopNLazyMaterializationSecondPhaseSegmentsRead`
| 第2フェーズで読み取った行数とアクセスしたSegment数 |
+| ローカルキャッシュ読み取り |
`TopNLazyMaterializationSecondPhaseLocalIOCount`、`TopNLazyMaterializationSecondPhaseLocalIOBytes`、`TopNLazyMaterializationSecondPhaseLocalIOTime`
| File Cacheから読み取った回数、バイト数、所要時間 |
+| リモート読み取り |
`TopNLazyMaterializationSecondPhaseRemoteIOCount`、`TopNLazyMaterializationSecondPhaseRemoteIOBytes`、`TopNLazyMaterializationSecondPhaseRemoteIOTime`
| リモートストレージから読み取った回数、バイト数、所要時間 |
+| キャッシュのスキップ | `TopNLazyMaterializationSecondPhaseSkipCacheIOCount` |
リモートから読み取り、File Cacheへ書き込まなかった回数 |
+| キャッシュ書き込み |
`TopNLazyMaterializationSecondPhaseWriteCacheBytes`、`TopNLazyMaterializationSecondPhaseWriteCacheIOTime`
| File Cacheへ書き込んだバイト数と所要時間 |
+
+書き戻し抑制ポリシーを有効にした場合は、次のパターンで動作を確認できます。
+
+| キャッシュ状態 | 期待されるメトリクス |
+| :--- | :--- |
+| 今回の読み取り範囲が完全にはキャッシュされていない |
`RemoteIOCount`、`RemoteIOBytes`、`SkipCacheIOCount`が0より大きく、`WriteCacheBytes`は0 |
+| 今回の読み取り範囲全体がダウンロード済みキャッシュブロックでカバーされている |
`LocalIOCount`と`LocalIOBytes`が0より大きく、`RemoteIOCount`、`RemoteIOBytes`、`WriteCacheBytes`は0
|
+
+ProfileにはBE別メトリクスもあります。`TopNLazyMaterializationSecondPhasePerBackend`にはBEの一覧が表示され、他のメトリクス名には`SecondPhase`の後に`PerBackend`が追加されます。たとえば、`TopNLazyMaterializationSecondPhasePerBackendRowsRead`と`TopNLazyMaterializationSecondPhasePerBackendWriteCacheBytes`です。各配列要素はインデックスによってBE一覧と対応し、同じクエリ内で複数回実行された第2フェーズFetchのデータを累積します。
+
+:::note
+`TopNLazyMaterializationSecondPhaseWriteCacheBytes`は遅延マテリアライゼーション第2フェーズだけを集計します。一般的なFile
Cacheメトリクスに書き込みが残っている場合は、まず第1フェーズまたは他のオペレータによる書き込みかどうかを確認してください。Profileの取得方法については、[Query
Profile分析](../query-profile.md)を参照してください。
+:::
+
### 実行中のTOPNクエリ最適化の効果確認
まず、`topn_opt_limit_threshold`を0に設定してTOPNクエリ最適化を無効にし、最適化が有効な場合と無効な場合のSQLの実行時間を比較します。
diff --git
a/versioned_docs/version-4.x/query-acceleration/optimization-technology-principle/topn-optimization.md
b/versioned_docs/version-4.x/query-acceleration/optimization-technology-principle/topn-optimization.md
index ca3263149cf..6a8d0ecc127 100644
---
a/versioned_docs/version-4.x/query-acceleration/optimization-technology-principle/topn-optimization.md
+++
b/versioned_docs/version-4.x/query-acceleration/optimization-technology-principle/topn-optimization.md
@@ -2,8 +2,8 @@
{
"title": "TOPN Query Optimization: ORDER BY LIMIT Acceleration Principles
and Configuration",
"language": "en",
- "description": "How does Doris accelerate ORDER BY LIMIT queries? This
article explains TOPN optimization principles, applicable limitations, session
parameters, and execution plan inspection methods.",
- "keywords": ["Doris TOPN optimization", "ORDER BY LIMIT acceleration",
"topn_opt_limit_threshold", "two-phase read", "RuntimePredicate", "Zonemap
filtering"]
+ "description": "How does Doris accelerate ORDER BY LIMIT queries? This
article explains TOPN optimization principles, applicable limitations, session
parameters, execution plan inspection methods, and the phase-2 File Cache
policy for lazy materialization in storage-compute separation deployments.",
+ "keywords": ["Doris TOPN optimization", "ORDER BY LIMIT acceleration",
"topn_opt_limit_threshold", "enable_topn_lazy_mat_phase2_no_write_file_cache",
"two-phase read", "File Cache", "RuntimePredicate", "Zonemap filtering"]
}
---
@@ -53,13 +53,14 @@ SELECT * FROM tablex WHERE xxx ORDER BY c1, c2 ... LIMIT n
## Configuration Parameters
-The following three parameters are all session variables. You can set them for
a single SQL statement or globally.
+The following four parameters are all session variables. You can set them for
a single SQL statement or globally.
| Parameter | Default | Effect | Tuning Suggestion |
| :--- | :--- | :--- | :--- |
| `topn_opt_limit_threshold` | 1024 | TOPN optimization is enabled only when
LIMIT n is less than this value | Set to `0` to disable the entire TOPN
optimization |
| `enable_two_phase_read_opt` | true | Whether to enable Optimization 3
(two-phase lazy materialization) | Set to `false` to disable Optimization 3
alone |
| `topn_filter_ratio` | 0.5 | Ratio threshold of LIMIT n to total table data |
When the LIMIT count exceeds half of the table data, the filter is no longer
generated |
+| `enable_topn_lazy_mat_phase2_no_write_file_cache` | false | In
storage-compute separation mode, controls whether phase 2 of lazy
materialization for Doris internal tables skips cache writeback on a File Cache
miss | Enable it only when phase-2 reads have low reuse and are likely to
pollute the cache |
<!-- Knowledge type: operation -->
<!-- Applicable scenarios: verifying whether TOPN optimization is enabled -->
@@ -78,7 +79,7 @@ EXPLAIN <your_sql>;
- `TOPN OPT`: **Optimization 1** (dynamic range filtering) is enabled
- `SORT LIMIT` under `VOlapScanNode`: **Optimization 2** (key-prefix
short-circuit read) is enabled
-- `OPT TWO PHASE`: **Optimization 3** (two-phase lazy materialization) is
enabled
+- `MaterializeNode` (or `OPT TWO PHASE` in older execution plans):
**Optimization 3** (two-phase lazy materialization) is enabled
**Example**:
@@ -103,6 +104,116 @@ EXPLAIN <your_sql>;
pushAggOp=NONE
```
+<!-- Knowledge type: configuration + operation + troubleshooting -->
+<!-- Applicable scenarios: controlling File Cache writes during TOPN lazy
materialization phase 2 in clusters with storage-compute separation -->
+
+## Control File Cache Writes During Lazy Materialization Phase 2
+
+In a cluster with storage-compute separation, phase 2 of TOPN lazy
materialization reads the remaining columns by the row IDs selected in phase 1.
When a small number of result rows are scattered across many Segments, the
cache blocks populated by these sparse reads may see little reuse and displace
hot data. In this case, enable
`enable_topn_lazy_mat_phase2_no_write_file_cache` so that phase 2 reads cache
misses directly from remote storage without writing them back to File Cache.
+
+This variable does not change query results. It changes only how phase 2
handles File Cache misses:
+
+| Setting | Phase-2 Read Behavior |
+| :--- | :--- |
+| `false` (default) | Uses the regular read-through and writeback policy: on a
cache miss, Doris reads remote data and writes the data to File Cache |
+| `true` | Reads local cache only when cache blocks in the `DOWNLOADED` state
fully cover the current read range. If any part is uncached or still
downloading, Doris reads the entire current range from remote storage without
creating or writing cache blocks |
+
+Before enabling this variable, note the following boundaries:
+
+- It takes effect only in storage-compute separation mode and controls only
phase 2 of TOPN lazy materialization for Doris internal tables. It currently
does not control phase-2 reads for external tables.
+- It supports Doris internal tables both with and without row store enabled.
+- It neither removes existing cache entries nor changes cache writes made by
phase 1, other queries, or other operators. The query's total File Cache writes
may therefore still be greater than zero.
+- It has no additional effect when File Cache is disabled or when the
execution plan does not contain a `MaterializeNode`.
+
+### Basic Usage
+
+The following example requires a cluster with storage-compute separation, File
Cache enabled on the BEs, and a user that can create and drop tables and insert
and query data in the target database. First, create a Duplicate Key internal
table:
+
+```sql
+DROP TABLE IF EXISTS topn_file_cache_demo;
+
+CREATE TABLE topn_file_cache_demo (
+ id BIGINT NOT NULL,
+ event_time DATETIME NOT NULL,
+ payload VARCHAR(128) NOT NULL
+)
+ENGINE=OLAP
+DUPLICATE KEY(id)
+DISTRIBUTED BY HASH(id) BUCKETS 1
+PROPERTIES (
+ "replication_num" = "1",
+ "light_schema_change" = "true"
+);
+
+INSERT INTO topn_file_cache_demo VALUES
+ (1, '2026-01-01 10:00:00', 'alpha'),
+ (2, '2026-01-02 10:00:00', 'beta'),
+ (3, '2026-01-03 10:00:00', 'gamma');
+```
+
+Enable Profile and the phase-2 no-write policy, inspect the execution plan,
and run the query:
+
+```sql
+SET enable_profile = true;
+SET profile_level = 2;
+SET enable_sql_cache = false;
+SET enable_query_cache = false;
+SET enable_topn_lazy_mat_phase2_no_write_file_cache = true;
+
+EXPLAIN SELECT id, payload
+FROM topn_file_cache_demo
+ORDER BY event_time DESC
+LIMIT 2;
+
+SELECT id, payload
+FROM topn_file_cache_demo
+ORDER BY event_time DESC
+LIMIT 2;
+```
+
+The execution plan should contain a `MaterializeNode`. The query returns the
following result regardless of whether the variable is enabled:
+
+```text
++----+---------+
+| id | payload |
++----+---------+
+| 3 | gamma |
+| 2 | beta |
++----+---------+
+2 rows in set
+```
+
+To restore the default cache writeback behavior, run:
+
+```sql
+SET enable_topn_lazy_mat_phase2_no_write_file_cache = false;
+```
+
+### Verify the Cache Policy in Profile
+
+After setting `profile_level` to `2`, inspect the following phase-2-specific
metrics under the execution operator corresponding to `MaterializeNode` in
Query Profile:
+
+| Dimension | Aggregate Metrics | Meaning |
+| :--- | :--- | :--- |
+| Read scale | `TopNLazyMaterializationSecondPhaseRowsRead`,
`TopNLazyMaterializationSecondPhaseSegmentsRead` | Number of rows read and
Segments accessed in phase 2 |
+| Local cache reads | `TopNLazyMaterializationSecondPhaseLocalIOCount`,
`TopNLazyMaterializationSecondPhaseLocalIOBytes`,
`TopNLazyMaterializationSecondPhaseLocalIOTime` | Count, bytes, and time of
reads from File Cache |
+| Remote reads | `TopNLazyMaterializationSecondPhaseRemoteIOCount`,
`TopNLazyMaterializationSecondPhaseRemoteIOBytes`,
`TopNLazyMaterializationSecondPhaseRemoteIOTime` | Count, bytes, and time of
reads from remote storage |
+| Cache bypass | `TopNLazyMaterializationSecondPhaseSkipCacheIOCount` | Number
of remote reads that were not written to File Cache |
+| Cache writes | `TopNLazyMaterializationSecondPhaseWriteCacheBytes`,
`TopNLazyMaterializationSecondPhaseWriteCacheIOTime` | Bytes written to File
Cache and time spent writing them |
+
+When the no-write policy is enabled, use the following patterns to verify its
behavior:
+
+| Cache State | Expected Metric Pattern |
+| :--- | :--- |
+| The current read range is not fully cached | `RemoteIOCount`,
`RemoteIOBytes`, and `SkipCacheIOCount` are greater than 0, while
`WriteCacheBytes` is 0 |
+| The current read range is fully covered by downloaded cache blocks |
`LocalIOCount` and `LocalIOBytes` are greater than 0, while `RemoteIOCount`,
`RemoteIOBytes`, and `WriteCacheBytes` are 0 |
+
+Profile also provides per-BE metrics.
`TopNLazyMaterializationSecondPhasePerBackend` lists the BEs. The other metric
names add `PerBackend` after `SecondPhase`, for example,
`TopNLazyMaterializationSecondPhasePerBackendRowsRead` and
`TopNLazyMaterializationSecondPhasePerBackendWriteCacheBytes`. Array elements
correspond to the BE list by index and accumulate data from multiple phase-2
fetches within the same query.
+
+:::note
+`TopNLazyMaterializationSecondPhaseWriteCacheBytes` covers only phase 2 of
lazy materialization. If general File Cache metrics still report writes, first
determine whether they come from phase 1 or another operator. For information
about obtaining a Profile, see [Query Profile Analysis](../query-profile.md).
+:::
+
<!-- Knowledge type: operation -->
<!-- Applicable scenarios: evaluating the actual benefit of TOPN optimization
-->
@@ -210,6 +321,10 @@ Set `enable_two_phase_read_opt = false`.
Confirm that TOPN optimization is not enabled on the MOR table. For MOR
tables, use the MOW model or avoid triggering this optimization path.
+**Q5: Why does the query still write to File Cache after I enable the phase-2
no-write policy?**
+
+The policy controls only phase 2 of TOPN lazy materialization for Doris
internal tables. Phase 1, other operators, and external-table reads may still
write to File Cache. Use `TopNLazyMaterializationSecondPhaseWriteCacheBytes` to
determine whether phase 2 performed cache writes instead of relying on the
query's total write volume.
+
## Quick Reference for Related Parameters
| Desired Effect | Setting |
@@ -218,3 +333,5 @@ Confirm that TOPN optimization is not enabled on the MOR
table. For MOR tables,
| Disable only two-phase lazy materialization | `SET enable_two_phase_read_opt
= false;` |
| Relax the LIMIT upper bound to cover more queries | Increase
`topn_opt_limit_threshold` appropriately |
| Adjust the ratio threshold for generating the filter | Modify
`topn_filter_ratio` |
+| Do not write phase-2 cache misses back to File Cache | `SET
enable_topn_lazy_mat_phase2_no_write_file_cache = true;` |
+| Restore the default phase-2 cache writeback behavior | `SET
enable_topn_lazy_mat_phase2_no_write_file_cache = false;` |
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]