新しい設定 allow_asynchronous_read_from_io_pool_for_merge_tree を使うと、読み取りスレッド数 (ストリーム) を、クエリ実行パイプラインの他の部分のスレッド数より多くできます。
通常、max_threads 設定は、並列読み取りスレッド数と並列クエリ処理スレッド数を制御します。

データはディスクから、カラムごとに「順番に」読み取られます。
非同期データ読み取り
新しい設定 allow_asynchronous_read_from_io_pool_for_merge_tree を使用すると、読み取りスレッド (ストリーム) の数を、クエリ実行パイプラインの他の部分のスレッド数より多くできます。これにより、CPU リソースが限られた ClickHouse Cloud サービスでコールドクエリを高速化し、I/O バウンドなクエリのパフォーマンスを向上できます。 この設定を有効にすると、読み取りスレッド数は max_streams_for_merge_tree_reading 設定で制御されます。

データは非同期に、異なるカラムから並列に読み取られます。
なお、読み取りスレッド (ストリーム) の数とクエリ実行パイプラインの他の部分のスレッド数との比率を設定するための max_streams_to_max_threads_ratio 設定もあります。ただし、ベンチマークでは max_streams_for_merge_tree_reading 設定ほどの効果は得られませんでした
optimize_read_in_order はどうでしょうか?
optimize_read_in_order 最適化 を使用すると、クエリのソート順がディスク上のデータの物理順序を反映している場合、ClickHouse はメモリ上でデータを再ソートする処理を 省略 できます。ただし、そのためにはデータを順序どおりに読み取る必要があります (非同期読み取りとは対照的です) 。

optimize_read_in_order 最適化は非同期読み取りより優先されます
ClickHouse が optimize_read_in_order 最適化 を適用できると判断した場合、allow_asynchronous_read_from_io_pool_for_merge_tree 設定は無視され、無効化されます。
上記すべてを示す例
-
UK Property Price Paid テーブルを作成してロードします
-
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 optimizationを適用できる場合の、 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 │
└───────────────────────────────────┘
-- 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 │
└───────────────────────────────────┘
-- optimize_read_in_order を無効にすることで allow_asynchronous_read_from_io_pool_for_merge_tree を強制できることに注意
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 │
└──────────────────────────────────────┘