Use max_insert_threads for plain INSERTs without materialized views#102961
Merged
Use max_insert_threads for plain INSERTs without materialized views#102961
Conversation
buildInsertPipeline was requesting max_threads ConcurrencyControl slots for all INSERTs regardless of pipeline width. For plain INSERTs without MVs the pipeline is 1-wide, so this wasted CC capacity and spawned unnecessary threads (up to ~10 for max_threads=16). Now we use max_insert_threads when no MVs are attached, and max_threads only when MVs are involved (their inner SELECTs benefit from full parallelism). Also adds a trace log in PipelineExecutor::allocateCPU to make CC slot allocation visible, and a regression test covering both cases. Fixes: #102947
Contributor
|
Workflow [PR], commit [c4f5e7e] Summary: ❌
AI ReviewSummaryThis PR changes Findings
💡 Nits
ClickHouse Rules
Final Verdict
|
ConcurrencyControl has an issue (#102947) where CC slots are allocated eagerly at query start, and spawnThreads has a race where it spawns threads faster than they can register as idle, resulting in many unnecessary threads being created. Until lazy CC slot allocation is implemented, we have no choice other than to set strict limits on the thread count for insert queries. buildInsertPipeline was requesting max_threads CC slots for all INSERTs regardless of pipeline width. For plain INSERTs without MVs the pipeline is 1-wide, so this wasted CC capacity and spawned unnecessary threads. Now we use max_insert_threads when no MVs are attached, and max_threads only when MVs are involved (their inner SELECTs benefit from full parallelism). Fixes: #102947
Style check requires specifying the log table name explicitly.
CheSema
added a commit
that referenced
this pull request
Apr 17, 2026
…ized settings Pin `input_format_parallel_parsing=0` in INSERT commands so that parallel parsing threads do not inflate `peak_threads_usage` beyond the threshold — the test measures INSERT pipeline concurrency, not parser parallelism. Add `SETTINGS optimize_if_transform_strings_to_enum = 0` to diagnostic queries against `system.query_log` to prevent a column name mismatch when randomized settings enable both this optimization and `parallel_replicas_local_plan`. CI report: #102961 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ized settings Pin `input_format_parallel_parsing=0` in INSERT commands so that parallel parsing threads do not inflate `peak_threads_usage` beyond the threshold — the test measures INSERT pipeline concurrency, not parser parallelism. Add `SETTINGS optimize_if_transform_strings_to_enum = 0` to diagnostic queries against `system.query_log` to prevent a column name mismatch when randomized settings enable both this optimization and `parallel_replicas_local_plan`. CI report: #102961 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
a6bb0a1 to
c208281
Compare
groeneai
added a commit
to groeneai/ClickHouse
that referenced
this pull request
Apr 18, 2026
Regression from ClickHouse#92141: server aborts with signal 6 during `loadDataPart` in debug and sanitizer builds when a part directory contains a leftover `txn_version.txt.tmp` file with no corresponding `txn_version.txt`. This state is produced by `VersionMetadataOnDisk::loadMetadata` case 2 (an incomplete write that was not atomically renamed). It returns a `VersionInfo` with `creation_tid = Tx::DummyTID` and `creation_csn = Tx::RolledBackCSN`. `Tx::DummyTID = {NonTransactionalCSN, DummyLocalTID, Nil} = {1, 2, Nil}` has `start_csn == NonTransactionalCSN` but `local_tid == DummyLocalTID` — which fails the invariant asserted in `TransactionID::isNonTransactional`. The new `VersionMetadata::validateInfo` (added by ClickHouse#92141) and `VersionInfo::wasInvolvedInTransaction` both call `isNonTransactional` on the loaded `creation_tid`, so the assertion aborts the server. Two changes: - `TransactionID::isNonTransactional`: widen the assertion to allow the `DummyTID` special case. The function still correctly returns `false` for `DummyTID` because `local_tid == DummyLocalTID != NonTransactionalLocalTID`. - `VersionMetadata::validateInfo`: early-return for rolled-back parts (`creation_csn == RolledBackCSN`). Such parts are marked `Outdated` immediately after loading by `MergeTreeData::loadDataPart` and cleaned up, so the live-part invariants validated here do not apply. CI reports showing the crash: - PR ClickHouse#103047: https://s3.amazonaws.com/clickhouse-test-reports/json.html?PR=103047&sha=ec0124d77b94c97a4b1b48049b0215b1dddb94a5&name_0=PR&name_1=Stateless%20tests%20%28amd_debug%2C%20distributed%20plan%2C%20s3%20storage%2C%20parallel%29 - PR ClickHouse#102961: same `Stateless tests (amd_debug, distributed plan, s3 storage, parallel)` check Regression test `04104_transaction_version_metadata_dummy_tid_load.sh` deterministically creates the scenario by dropping a bogus `txn_version.txt.tmp` into a part directory and running `DETACH` + `ATTACH`. Before the fix the server aborts with signal 6 at `TransactionID.h:90`; after the fix the rolled-back part is marked `Outdated` and invisible. Session: cron:clickhouse-ci-task-worker:20260418-221500
1 task
DatabaseReplicated: `query_log` lookup by `query_id` assumes single-node execution; replicated setup may miss entries or return duplicates from other replicas. AsyncInsert: injected `async_insert=1` queues the INSERT and returns immediately, so `peak_threads_usage` reflects only the queuing step, not the MV processing pipeline the test is designed to verify. CI report: #102961 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ParallelReplicas settings alter query execution plans and thread allocation, making `peak_threads_usage` checks unreliable. S3 I/O threads (multi-part uploads, cache connections) inflate `peak_threads_usage` beyond the pipeline thread count the test measures. CI report: https://s3.amazonaws.com/clickhouse-test-reports/json.html?PR=102961&sha=43b3cf5f2a16a3ddc9683efa36016d69558b0531&name_0=PR PR: #102961 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Contributor
LLVM Coverage Report
Changed lines: 100.00% (4/4) · Uncovered code |
serxa
approved these changes
Apr 20, 2026
robot-ch-test-poll4
added a commit
that referenced
this pull request
Apr 21, 2026
Cherry pick #102961 to 26.1: Use max_insert_threads for plain INSERTs without materialized views
robot-clickhouse
added a commit
that referenced
this pull request
Apr 21, 2026
…thout materialized views
robot-ch-test-poll4
added a commit
that referenced
this pull request
Apr 21, 2026
Cherry pick #102961 to 26.2: Use max_insert_threads for plain INSERTs without materialized views
robot-clickhouse
added a commit
that referenced
this pull request
Apr 21, 2026
…thout materialized views
robot-ch-test-poll4
added a commit
that referenced
this pull request
Apr 21, 2026
Cherry pick #102961 to 26.3: Use max_insert_threads for plain INSERTs without materialized views
robot-clickhouse
added a commit
that referenced
this pull request
Apr 21, 2026
…thout materialized views
clickhouse-gh Bot
added a commit
that referenced
this pull request
Apr 21, 2026
Backport #102961 to 26.1: Use max_insert_threads for plain INSERTs without materialized views
clickhouse-gh Bot
added a commit
that referenced
this pull request
Apr 21, 2026
Backport #102961 to 26.2: Use max_insert_threads for plain INSERTs without materialized views
CheSema
added a commit
that referenced
this pull request
Apr 22, 2026
Backport #102961 to 26.3: Use max_insert_threads for plain INSERTs without materialized views
clickhouse-gh Bot
pushed a commit
that referenced
this pull request
Apr 30, 2026
Use max_insert_threads for plain INSERTs without materialized views
clickhouse-gh Bot
added a commit
that referenced
this pull request
Apr 30, 2026
Backport #102961 to 25.12: Use max_insert_threads for plain INSERTs without materialized views
CheSema
added a commit
that referenced
this pull request
Apr 30, 2026
Backport #102961 to 25.10: Use max_insert_threads for plain INSERTs without materialized views
kewin-robetti
pushed a commit
to viasoftkorp/ClickHouse
that referenced
this pull request
May 1, 2026
…thread-count Use max_insert_threads for plain INSERTs without materialized views
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ConcurrencyControl has an issue (#102947) where CC slots are allocated eagerly at query start, and
spawnThreadshas a race where it spawns threads faster than they can register as idle, resulting in many unnecessary threads being created.Until lazy CC slot allocation is implemented, we have no choice other than to set strict limits on the thread count for insert queries.
buildInsertPipelinewas requestingmax_threadsCC slots for all INSERTs regardless of pipeline width. For plain INSERTs without MVs the pipeline is 1-wide, so this wasted CC capacity and spawned unnecessary threads.Now we use
max_insert_threadswhen no MVs are attached, andmax_threadsonly when MVs are involved (their inner SELECTs benefit from full parallelism).Mitigates #102947
Changelog category (leave one):
Changelog entry
Plain INSERTs without materialized views no longer request excessive ConcurrencyControl slots and threads (
max_threadsinstead ofmax_insert_threads), preventing CC slot starvation and thread count blowup on clusters with high INSERT throughput.Documentation entry for user-facing changes