matrixorigin / matrixorigin/matrixone
[Bug]: Window internal sorting ignores sort_spill_mem and cannot spill
- Dominant language
- Go
- Stars
- 1.9k
- Forks
- 311
- Avg merge
- 1d 3h
- Merged PRs (30d)
- 768
Description
## 现状
MatrixOne 的 `Window` 算子会物化并在内存中排序整个输入分区,不会使用现有的 sort spill 路径。即使将 `sort_spill_mem` 设为 `1`,窗口计划仍没有 `SpillRows`/`SpillSize`,其内存随分区行数和窗口参数宽度线性增长。
以下结果来自最新 `main` `bb358ea76aeb44a6eed5079616e7e75ba35e75b9`,两 CN 本地集群:
```sql
SET @@max_dop = 1;
SET @@sort_spill_mem = 1;
EXPLAIN (ANALYZE TRUE)
SELECT SUM(rn)
FROM (
SELECT ROW_NUMBER() OVER (ORDER BY result DESC) rn
FROM generate_series(1, 2000000) g
) q;
```
`Window` 在 200K、1M、2M 行下分别报告约 `1.65 MiB`、`7.75 MiB`、`15.38 MiB` 内存,没有 spill。宽窗口参数更明显:
```sql
EXPLAIN (ANALYZE TRUE)
SELECT SUM(LENGTH(fv))
FROM (
SELECT FIRST_VALUE(
CONCAT(LPAD(result, 6, '0'), REPEAT('x', 1018))
) OVER (
ORDER BY result
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) fv
FROM generate_series(1, 100000) g
) q;
```
- 50K 行:`Window MemorySize=58.22 MiB`;
- 100K 行:`Window MemorySize=108.20 MiB`;
- 两个计划均无 `SpillRows`/`SpillSize`。
同一会话中的普通排序控制可以落盘:
```sql
EXPLAIN (ANALYZE TRUE)
SELECT id, d FROM fact ORDER BY d DESC, u ASC, id;
```
200K 行报告 `Sort SpillRows=200000, SpillSize=5.34 MiB`,说明阈值生效且临时存储可用。窗口查询在高/低阈值下结果相同;这里的问题是大分区没有磁盘降级路径,并非当前小数据结果错误。
## 代码位置
`pkg/sql/colexec/window/window.go` 的 receive 阶段使用 `AppendWithCopy` 物化输入,eval 阶段再调用 `processOrder`;`pkg/sql/colexec/window/types.go` 的 container 仅保存内存 batch、排序选择向量和窗口状态,没有 spill 状态或临时文件路径。Window 目录也没有接入 `spillutil`/`mergeorder`。
## 期望
- `sort_spill_mem` 不应只作用于普通 `Sort`,然后被执行相同排序工作的 Window 路径静默绕过;大窗口分区应进入可配置的 spill 路径,或在规划阶段复用可 spill 的外部排序并让 Window 流式消费;
- 明确 Window 使用 `sort_spill_mem` 还是独立阈值;
- `EXPLAIN ANALYZE` 暴露 Window 的 spill 行数和字节数;
- 回归覆盖窄/宽参数、单/多分区、`ROWS`/`RANGE`、rank/lag/lead/value/aggregate window,并校验 spill 与内存执行的结果一致性。
Contributor guide
Assessment
This issue has not been assessed yet.