Skip to content

Commit b319ff1

Browse files
committed
Adaptive async insert timeout adjustments for large limits
Customers may have a maximum asynchronous timeout limit as large as 100 seconds. This doesn't work well with the current algorithm, which uses a default minimum limit of 50 milliseconds. * Use the maximum limit as the initial value for the adaptive algorithm; * Introduce async_insert_busy_timeout_max_limits_ratio to determine the maximum ratio between the minimum and maximum limits. If the ratio between async_insert_busy_timeout_min_ms and async_insert_busy_timeout_max_ms exceeds this value, increase the minimum limit.
1 parent d401998 commit b319ff1

File tree

4 files changed

+28
-4
lines changed

4 files changed

+28
-4
lines changed

src/Core/Settings.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -775,10 +775,11 @@ class IColumn;
775775
M(UInt64, async_insert_max_query_number, 450, "Maximum number of insert queries before being inserted", 0) \
776776
M(Milliseconds, async_insert_poll_timeout_ms, 10, "Timeout for polling data from asynchronous insert queue", 0) \
777777
M(Bool, async_insert_use_adaptive_busy_timeout, true, "If it is set to true, use adaptive busy timeout for asynchronous inserts", 0) \
778-
M(Milliseconds, async_insert_busy_timeout_min_ms, 50, "If auto-adjusting is enabled through async_insert_use_adaptive_busy_timeout, minimum time to wait before dumping collected data per query since the first data appeared. It also serves as the initial value for the adaptive algorithm", 0) \
779-
M(Milliseconds, async_insert_busy_timeout_max_ms, 200, "Maximum time to wait before dumping collected data per query since the first data appeared.", 0) ALIAS(async_insert_busy_timeout_ms) \
778+
M(Milliseconds, async_insert_busy_timeout_min_ms, 50, "If auto-adjusting is enabled through async_insert_use_adaptive_busy_timeout, minimum time to wait before dumping collected data per query since the first data appeared.", 0) \
779+
M(Milliseconds, async_insert_busy_timeout_max_ms, 200, "Maximum time to wait before dumping collected data per query since the first data appeared. It also serves as the initial value for the adaptive algorithm.", 0) ALIAS(async_insert_busy_timeout_ms) \
780780
M(Double, async_insert_busy_timeout_increase_rate, 0.2, "The exponential growth rate at which the adaptive asynchronous insert timeout increases", 0) \
781781
M(Double, async_insert_busy_timeout_decrease_rate, 0.2, "The exponential growth rate at which the adaptive asynchronous insert timeout decreases", 0) \
782+
M(Double, async_insert_busy_timeout_max_limits_ratio, 20.0, "The maximum allowable ratio between the minimum and maximum limits for adaptive asynchronous insert timeout. This may increase the minimum limit set by the async_insert_busy_timeout_min_ms setting. It is expected to be greater or equal than 1.0", 0) \
782783
\
783784
M(UInt64, remote_fs_read_max_backoff_ms, 10000, "Max wait time when trying to read data for remote disk", 0) \
784785
M(UInt64, remote_fs_read_backoff_max_tries, 5, "Max attempts to read with backoff", 0) \

src/Core/SettingsChangesHistory.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ static std::map<ClickHouseVersion, SettingsChangesHistory::SettingsChanges> sett
121121
{"azure_max_upload_part_size", 5ull*1024*1024*1024, 5ull*1024*1024*1024, "The maximum size of part to upload during multipart upload to Azure blob storage."},
122122
{"azure_upload_part_size_multiply_factor", 2, 2, "Multiply azure_min_upload_part_size by this factor each time azure_multiply_parts_count_threshold parts were uploaded from a single write to Azure blob storage."},
123123
{"azure_upload_part_size_multiply_parts_count_threshold", 500, 500, "Each time this number of parts was uploaded to Azure blob storage, azure_min_upload_part_size is multiplied by azure_upload_part_size_multiply_factor."},
124+
{"async_insert_busy_timeout_max_limits_ratio", 20.0, 20.0, "The maximum allowable ratio between the minimum and maximum limits for adaptive asynchronous insert timeout." },
124125
}},
125126
{"24.2", {{"allow_suspicious_variant_types", true, false, "Don't allow creating Variant type with suspicious variants by default"},
126127
{"validate_experimental_and_suspicious_types_inside_nested_types", false, true, "Validate usage of experimental and suspicious types inside nested types"},

src/Interpreters/AsynchronousInsertQueue.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ AsynchronousInsertQueue::AsynchronousInsertQueue(ContextPtr context_, size_t poo
213213

214214
for (size_t i = 0; i < pool_size; ++i)
215215
queue_shards[i].busy_timeout_ms
216-
= std::min(Milliseconds(settings.async_insert_busy_timeout_min_ms), Milliseconds(settings.async_insert_busy_timeout_max_ms));
216+
= std::max(Milliseconds(settings.async_insert_busy_timeout_min_ms), Milliseconds(settings.async_insert_busy_timeout_max_ms));
217217

218218
for (size_t i = 0; i < pool_size; ++i)
219219
dump_by_first_update_threads.emplace_back([this, i] { processBatchDeadlines(i); });
@@ -483,7 +483,10 @@ AsynchronousInsertQueue::Milliseconds AsynchronousInsertQueue::getBusyWaitTimeou
483483
return settings.async_insert_busy_timeout_max_ms;
484484

485485
const auto max_ms = Milliseconds(settings.async_insert_busy_timeout_max_ms);
486-
const auto min_ms = std::min(std::max(Milliseconds(settings.async_insert_busy_timeout_min_ms), Milliseconds(1)), max_ms);
486+
const double limits_ratio = settings.async_insert_busy_timeout_max_limits_ratio;
487+
488+
const auto min_ms = std::clamp(
489+
Milliseconds(settings.async_insert_busy_timeout_min_ms), std::chrono::ceil<Milliseconds>(max_ms / limits_ratio), max_ms);
487490

488491
auto normalize = [&min_ms, &max_ms](const auto & t_ms) { return std::min(std::max(t_ms, min_ms), max_ms); };
489492

@@ -543,6 +546,9 @@ void AsynchronousInsertQueue::validateSettings(const Settings & settings, Logger
543546

544547
if (settings.async_insert_busy_timeout_decrease_rate <= 0)
545548
throw Exception(ErrorCodes::INVALID_SETTING_VALUE, "Setting 'async_insert_busy_timeout_decrease_rate' must be greater than zero");
549+
550+
if (settings.async_insert_busy_timeout_max_limits_ratio <= 1.0)
551+
throw Exception(ErrorCodes::INVALID_SETTING_VALUE, "Setting 'async_insert_busy_timeout_max_limits_ratio' must be greater or equal than 1.0");
546552
}
547553

548554
void AsynchronousInsertQueue::flushAll()

tests/queries/0_stateless/02968_adaptive_async_insert_timeout.sql

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,15 @@ INSERT INTO async_insert_mt_test
3131
async_insert_busy_timeout_min_ms=500
3232
VALUES (3, []), (1, [1, 3]), (2, [7, 8]), (4, [5, 9]), (5, [2, 6]);
3333

34+
INSERT INTO async_insert_mt_test
35+
SETTINGS
36+
async_insert=1,
37+
wait_for_async_insert=1,
38+
async_insert_busy_timeout_min_ms=10,
39+
async_insert_busy_timeout_ms=5000,
40+
async_insert_busy_timeout_max_limits_ratio=50
41+
VALUES (3, []), (1, [1, 3]), (2, [7, 8]), (4, [5, 9]), (5, [2, 6]);
42+
3443

3544
INSERT INTO async_insert_mt_test
3645
SETTINGS
@@ -47,5 +56,12 @@ INSERT INTO async_insert_mt_test
4756
async_insert_busy_timeout_decrease_rate=-1.0
4857
VALUES (3, []), (1, [1, 3]), (2, [7, 8]), (4, [5, 9]), (5, [2, 6]); -- { serverError INVALID_SETTING_VALUE }
4958

59+
INSERT INTO async_insert_mt_test
60+
SETTINGS
61+
async_insert=1,
62+
wait_for_async_insert=1,
63+
async_insert_busy_timeout_max_limits_ratio=0
64+
VALUES (3, []), (1, [1, 3]), (2, [7, 8]), (4, [5, 9]), (5, [2, 6]); -- { serverError INVALID_SETTING_VALUE }
65+
5066

5167
DROP TABLE IF EXISTS async_insert_mt_test;

0 commit comments

Comments
 (0)