Clickhouse has special options "do_not_merge_across_partitions_select_final" for ReplaceMergeTree Engine, which allows make fast select on the "optimized" partitions. Unfortunate you have to run manually (crontab)  "OPTIMIZE TABLE ... PARTITION ... FINAL" . 

It will be great to have some options which will tell Clickhouse to compact older partitions on some conditions:

i.e.
```
CREATE TABLE select_final (t DateTime, x Int32, string String) ENGINE = ReplacingMergeTree() PARTITION BY toYYYYMMDD(t) ORDER BY (x, t)  SETTINGS optimize_partition_after = 3600
```
Clickhouse will check if a partition is older than 3600 seconds and has multiple parts and in such condition will do automatically optimization (compaction) 

P.S. we just discussed with @alexey-milovidov about this options :-) 




{
    size_t scheduled_tasks_count = CurrentMetrics::values[CurrentMetrics::BackgroundMergesAndMutationsPoolTask].load(std::memory_order_relaxed);
    return getMaxSourcePartsSizeForMerge(max_tasks_count, scheduled_tasks_count);
}
UInt64 MergeTreeDataMergerMutator::getMaxSourcePartsSizeForMerge(size_t max_count, size_t scheduled_tasks_count) const
{
    if (scheduled_tasks_count > max_count)
    {
        throw Exception(ErrorCodes::LOGICAL_ERROR,
            "Logical error: invalid argument passed to getMaxSourcePartsSize: scheduled_tasks_count = {} > max_count = {}",
            scheduled_tasks_count, max_count);
    }
    size_t free_entries = max_count - scheduled_tasks_count;
    const auto data_settings = data.getSettings();
    
    
    
    UInt64 max_size = 0;
    if (scheduled_tasks_count <= 1 || free_entries >= data_settings->number_of_free_entries_in_pool_to_lower_max_size_of_merge)
        max_size = data_settings->max_bytes_to_merge_at_max_space_in_pool;
    else
        max_size = static_cast<UInt64>(interpolateExponential(
            data_settings->max_bytes_to_merge_at_min_space_in_pool,
            data_settings->max_bytes_to_merge_at_max_space_in_pool,
            static_cast<double>(free_entries) / data_settings->number_of_free_entries_in_pool_to_lower_max_size_of_merge));
    return std::min(max_size, static_cast<UInt64>(data.getStoragePolicy()->getMaxUnreservedFreeSpace() / DISK_USAGE_COEFFICIENT_TO_SELECT));
}
UInt64 MergeTreeDataMergerMutator::getMaxSourcePartSizeForMutation() const