Statistics
https://play.clickhouse.com/play?user=play#c2VsZWN0IAp0b1N0YXJ0T2ZIb3VyKGNoZWNrX3N0YXJ0X3RpbWUpIGFzIGQsCmNvdW50KCksICBncm91cFVuaXFBcnJheShwdWxsX3JlcXVlc3RfbnVtYmVyKSwgIGFueShyZXBvcnRfdXJsKQpmcm9tIGNoZWNrcyB3aGVyZSAnMjAyMi0wNi0wMScgPD0gY2hlY2tfc3RhcnRfdGltZSBhbmQgdGVzdF9uYW1lIGxpa2UgJyUwMjQ5MV9wYXJ0X2xvZ19oYXNfdGFibGVfdXVpZCUnIGFuZCB0ZXN0X3N0YXR1cyBpbiAoJ0ZBSUwnLCAnRkxBS1knKSBncm91cCBieSBkIG9yZGVyIGJ5IGQgZGVzYw==

Some times there are not output from requests.
{
    auto lock = lockParts();
    Int64 max_block_num = 0;
    for (const DataPartPtr & part : data_parts_by_info)
        max_block_num = std::max({max_block_num, part->info.max_block, part->info.mutation});
    return max_block_num;
}
void MergeTreeData::loadDataPartsFromDisk(
    MutableDataPartsVector & broken_parts_to_detach,
    MutableDataPartsVector & duplicate_parts_to_remove,
    ThreadPool & pool,
    size_t num_parts,
    std::queue<std::vector<std::pair<String, DiskPtr>>> & parts_queue,
    bool skip_sanity_checks,
    const MergeTreeSettingsPtr & settings)
{
    
    pool.setMaxThreads(std::min(static_cast<size_t>(settings->max_part_loading_threads), num_parts));
    size_t num_threads = pool.getMaxThreads();
    LOG_DEBUG(log, "Going to use {} threads to load parts", num_threads);
    std::vector<size_t> parts_per_thread(num_threads, num_parts / num_threads);
    for (size_t i = 0ul; i < num_parts % num_threads; ++i)
        ++parts_per_thread[i];