跳到主要内容

同步数据读取

·4 分钟阅读
新的设置 `allow_asynchronous_read_from_io_pool_for_merge_tree` 允许读取线程(流)的数量高于查询执行管道其余部分的线程数。

同步数据读取

新的设置 allow_asynchronous_read_from_io_pool_for_merge_tree 允许读取线程(流)的数量高于查询执行管道其余部分的线程数。

通常,max_threads 设置控制并行读取线程和并行查询处理线程的数量

Untitled scene

数据从磁盘“按顺序”逐列读取。

异步数据读取

新的设置 allow_asynchronous_read_from_io_pool_for_merge_tree 允许读取线程(流)的数量高于查询执行管道其余部分的线程数,以加速低 CPU ClickHouse Cloud 服务上的冷查询,并提高 I/O 密集型查询的性能。启用此设置后,读取线程的数量由 max_streams_for_merge_tree_reading 设置控制

Untitled scene

数据以异步方式从不同列并行读取。

请注意,还有 max_streams_to_max_threads_ratio 设置用于配置读取线程(流)数量与查询执行管道其余部分线程数之间的比率。但是,在基准测试中,它不如 max_streams_for_merge_tree_reading 设置有效

optimize_read_in_order 呢?

使用 optimize_read_in_order 优化,如果查询排序顺序反映磁盘上数据的物理顺序,ClickHouse 可以跳过在内存中重新排序数据,但这需要按顺序读取数据(与异步读取相反)

Untitled scene

optimize_read_in_order 优先于异步读取

当 ClickHouse 看到可以应用 optimize_read_in_order 优化时,将忽略/禁用 allow_asynchronous_read_from_io_pool_for_merge_tree 设置。

演示以上所有内容的示例

  • 创建并加载 英国房产价格支付表

  • 检查 max_threads 的设置值(默认为 ClickHouse 在执行查询的节点上看到的 CPU 核心数)

SELECT getSetting('max_threads');


┌─getSetting('max_threads')─┐
│ 10 │
└───────────────────────────┘
  • 检查查询管道,默认线程数用于读取和处理数据
EXPLAIN PIPELINE
SELECT *
FROM uk_price_paid;

┌─explain──────────────────────┐
│ (Expression) │
│ ExpressionTransform × 10 │
│ (ReadFromMergeTree) │
│ MergeTreeThread × 10 0 → 1 │
└──────────────────────────────┘
  • 检查查询管道,60 个异步读取线程和默认线程数用于查询执行管道的其余部分
EXPLAIN PIPELINE
SELECT *
FROM uk_price_paid
SETTINGS
allow_asynchronous_read_from_io_pool_for_merge_tree = 1,
max_streams_for_merge_tree_reading = 60;


┌─explain────────────────────────┐
│ (Expression) │
│ ExpressionTransform × 10 │
│ (ReadFromMergeTree) │
│ Resize 60 → 10 │
│ MergeTreeThread × 60 0 → 1 │
└────────────────────────────────┘
  • 检查查询管道,20 个线程用于读取和处理数据
EXPLAIN PIPELINE
SELECT *
FROM uk_price_paid
SETTINGS
max_threads = 20;


┌─explain──────────────────────┐
│ (Expression) │
│ ExpressionTransform × 20 │
│ (ReadFromMergeTree) │
│ MergeTreeThread × 20 0 → 1 │
└──────────────────────────────┘
  • 检查查询管道,60 个异步读取线程和 20 个线程用于查询执行管道的其余部分
EXPLAIN PIPELINE
SELECT *
FROM uk_price_paid
SETTINGS
max_threads = 20,
allow_asynchronous_read_from_io_pool_for_merge_tree = 1,
max_streams_for_merge_tree_reading = 60;


┌─explain────────────────────────┐
│ (Expression) │
│ ExpressionTransform × 20 │
│ (ReadFromMergeTree) │
│ Resize 60 → 20 │
│ MergeTreeThread × 60 0 → 1 │
└────────────────────────────────┘
  • 检查查询管道,当可以应用 optimize_read_in_order 优化时,60 个异步读取线程和 20 个线程用于查询执行管道的其余部分
EXPLAIN PIPELINE
SELECT *
FROM uk_price_paid
ORDER BY postcode1, postcode2
SETTINGS
max_threads = 20,
allow_asynchronous_read_from_io_pool_for_merge_tree= 1,
max_streams_for_merge_tree_reading= 60;


┌─explain───────────────────────────┐
│ (Expression) │
│ ExpressionTransform │
│ (Sorting) │
│ MergingSortedTransform 20 → 1 │
│ (Expression) │
│ ExpressionTransform × 20 │
│ (ReadFromMergeTree) │
│ MergeTreeInOrder × 20 0 → 1 │
└───────────────────────────────────┘


-- note that this is equivalent to disabling allow_asynchronous_read_from_io_pool_for_merge_tree

EXPLAIN PIPELINE
SELECT *
FROM uk_price_paid
ORDER BY postcode1, postcode2
SETTINGS
max_threads = 20,
allow_asynchronous_read_from_io_pool_for_merge_tree = 0,
max_streams_for_merge_tree_reading = 0;


┌─explain───────────────────────────┐
│ (Expression) │
│ ExpressionTransform │
│ (Sorting) │
│ MergingSortedTransform 20 → 1 │
│ (Expression) │
│ ExpressionTransform × 20 │
│ (ReadFromMergeTree) │
│ MergeTreeInOrder × 20 0 → 1 │
└───────────────────────────────────┘

-- note that you can enforce allow_asynchronous_read_from_io_pool_for_merge_tree by disabling optimize_read_in_order

EXPLAIN PIPELINE
SELECT *
FROM uk_price_paid
ORDER BY
postcode1 ASC,
postcode2 ASC
SETTINGS
max_threads = 20,
allow_asynchronous_read_from_io_pool_for_merge_tree = 1,
max_streams_for_merge_tree_reading = 60,
optimize_read_in_order = 0;


┌─explain──────────────────────────────┐
│ (Expression) │
│ ExpressionTransform │
│ (Sorting) │
│ MergingSortedTransform 20 → 1 │
│ MergeSortingTransform × 20 │
│ (Expression) │
│ ExpressionTransform × 20 │
│ (ReadFromMergeTree) │
│ Resize 60 → 20 │
│ MergeTreeThread × 60 0 → 1 │
└──────────────────────────────────────┘