真实尝试用多组配置触发ORDER BY排序落盘,诚实记录未能复现出External Group By那样清晰的落盘证据的完整过程。
代码CREATE TABLE demo.sorttest (k UInt64, v String) ENGINE=MergeTree ORDER BY tuple(); INSERT INTO demo.sorttest SELECT rand64(), repeat('x', 200) FROM numbers(3000000); -- v不是排序键,ORDER BY v,k真实要对全表做一次和主键无关的排序 SELECT k FROM demo.sorttest ORDER BY v, k SETTINGS max_bytes_before_external_sort=52428800; -- 落盘阈值50MB
prefer_external_sort_block_bytes 16744704 (约16MB) max_bytes_before_external_sort 0 ← 绝对值阈值真实默认是0(关闭) max_bytes_ratio_before_external_sort 0.5 ← 真实默认走的是比例阈值:用满一半可用内存才落盘 min_external_sort_block_bytes 104857600 (约100MB,单个落盘块的最小体积)
本机这个版本(26.9.4)默认真实不是用一个固定的字节数阈值来决定要不要落盘,而是用max_bytes_ratio_before_external_sort这个比例(默认0.5,也就是排序缓冲区用到可用内存的一半才触发落盘),这跟上一篇《External Group By》验证的max_bytes_before_external_group_by固定字节数阈值是不同的设计。
SETTINGS max_bytes_before_external_sort=52428800 → memory 1.06GB, files=0
SETTINGS max_bytes_ratio_before_external_sort=0.05, max_memory_usage=1.5G → memory 1.06GB, files=0
SETTINGS 同上 + max_threads=1 → memory 0.68GB, files=0
SETTINGS max_bytes_before_external_sort=104857600, max_threads=1 → memory 0.68GB, files=0
EXPLAIN PIPELINE SELECT k FROM demo.sorttest ORDER BY v, k;
→ (Sorting)
MergeSortingTransform
LimitsCheckingTransform
PartialSortingTransform ← 真实的排序执行节点,但没看到任何落盘相关节点
SELECT name FROM system.events WHERE name ILIKE '%spill%';
→ AdaptiveAggregationSharedTableSpills ← 真实唯一带spill的事件,是聚合专属,不是排序的每一步都是本文上面用真实ClickHouse跑出来的原始结果,包括没有成功复现的部分。
max_bytes_before_external_sort/max_bytes_ratio_before_external_sort