Passer au contenu principal
Le nouveau paramètre allow_asynchronous_read_from_io_pool_for_merge_tree permet que le nombre de threads de lecture (flux) soit supérieur au nombre de threads dans le reste du pipeline d’exécution de la requête. Normalement, le paramètre max_threads contrôle le nombre de threads de lecture parallèles et de threads de traitement des requêtes parallèles : Les données sont lues « dans l’ordre », colonne après colonne, à partir du disque.

Lecture asynchrone des données

Le nouveau paramètre allow_asynchronous_read_from_io_pool_for_merge_tree permet d’avoir plus de threads de lecture (flux) que de threads dans le reste du pipeline d’exécution des requêtes afin d’accélérer les requêtes à froid sur des services ClickHouse Cloud à faible capacité CPU et d’améliorer les performances des requêtes limitées par les E/S. Lorsque ce paramètre est activé, le nombre de threads de lecture est contrôlé par le paramètre max_streams_for_merge_tree_reading : Les données sont lues de manière asynchrone, en parallèle, à partir de différentes colonnes. Notez qu’il existe également le paramètre max_streams_to_max_threads_ratio pour configurer le ratio entre le nombre de threads de lecture (flux) et le nombre de threads dans le reste du pipeline d’exécution des requêtes. Cependant, lors des benchmarks, il n’a pas été aussi utile que le paramètre max_streams_for_merge_tree_reading

Qu’en est-il d’optimize_read_in_order ?

Avec l’optimize_read_in_order optimization, ClickHouse peut éviter de retrier les données en mémoire si l’ordre de tri des requêtes reflète l’ordre physique des données sur le disque, mais cela exige de lire les données dans l’ordre (par opposition à une lecture asynchrone) :

optimize_read_in_order est prioritaire sur la lecture asynchrone

Lorsque ClickHouse constate que optimize_read_in_order optimization peut être appliquée, le paramètre allow_asynchronous_read_from_io_pool_for_merge_tree est alors ignoré / désactivé.

Exemple illustrant tout ce qui précède

  • Créez et chargez la table UK Property Price Paid
  • Vérifiez la valeur définie de max_threads (par défaut, le nombre de cœurs de CPU que ClickHouse voit sur le nœud exécutant la requête
SELECT getSetting('max_threads');

┌─getSetting('max_threads')─┐
│                        10 │
└───────────────────────────┘
  • Vérifier le pipeline d’exécution de la requête avec le nombre de threads par défaut, pour la lecture comme pour le traitement des données
EXPLAIN PIPELINE
SELECT *
FROM uk_price_paid;

┌─explain──────────────────────┐
│ (Expression)                 │
│ ExpressionTransform × 10     │
│   (ReadFromMergeTree)        │
│   MergeTreeThread × 10 0 → 1 │
└──────────────────────────────┘
  • Vérifiez le pipeline de la requête avec 60 threads de lecture asynchrones et le nombre de threads par défaut pour le reste du pipeline d’exécution de la requête
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 │
└────────────────────────────────┘
  • Vérifiez le pipeline d’exécution de la requête avec 20 threads pour la lecture et le traitement des données
EXPLAIN PIPELINE
SELECT *
FROM uk_price_paid
SETTINGS
    max_threads = 20;

┌─explain──────────────────────┐
│ (Expression)                 │
│ ExpressionTransform × 20     │
│   (ReadFromMergeTree)        │
│   MergeTreeThread × 20 0 → 1 │
└──────────────────────────────┘
  • Vérifiez le pipeline de requête avec 60 threads de lecture asynchrone et 20 autres pour le reste du pipeline d’exécution de la requête
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 │
└────────────────────────────────┘
  • Vérifiez le pipeline de requête avec 60 threads de lecture asynchrone et 20 threads pour le reste du pipeline d’exécution de la requête lorsque l’optimisation optimize_read_in_order optimization peut être appliquée
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 │
└──────────────────────────────────────┘

Dernière modification le 29 juin 2026