If they are defined, they can override table-level settings.
{
    const auto settings = getSettings();
    if (parts_to_remove.size() > 1 && settings->max_part_removal_threads > 1 && parts_to_remove.size() > settings->concurrent_part_removal_threshold)
    {
        
        size_t num_threads = std::min<size_t>(settings->max_part_removal_threads, parts_to_remove.size());
        ThreadPool pool(num_threads);
        
        for (const DataPartPtr & part : parts_to_remove)
        {
            pool.scheduleOrThrowOnError([&, thread_group = CurrentThread::getGroup()]
            {
                if (thread_group)
                    CurrentThread::attachToIfDetached(thread_group);
                LOG_DEBUG(log, "Removing part from filesystem {}", part->name);
                part->remove();
            });
        }
        pool.wait();
    }
    else
    {
        for (const DataPartPtr & part : parts_to_remove)
        {
            LOG_DEBUG(log, "Removing part from filesystem {}", part->name);
            part->remove();
        }
    }
}
size_t MergeTreeData::clearOldWriteAheadLogs()