2019-04-15 09:30:45 +00:00
|
|
|
#include <Storages/MergeTree/MergeTreeDataPartTTLInfo.h>
|
|
|
|
#include <IO/ReadHelpers.h>
|
|
|
|
#include <IO/WriteHelpers.h>
|
2019-10-17 16:01:28 +00:00
|
|
|
#include <Common/quoteString.h>
|
2020-09-02 10:30:04 +00:00
|
|
|
#include <algorithm>
|
2019-04-15 09:30:45 +00:00
|
|
|
|
2021-10-02 07:13:14 +00:00
|
|
|
#include <base/JSON.h>
|
2019-04-15 09:30:45 +00:00
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2022-05-26 15:48:08 +00:00
|
|
|
void MergeTreeDataPartTTLInfo::update(time_t time)
|
|
|
|
{
|
|
|
|
if (time && (!min || time < min))
|
|
|
|
min = time;
|
|
|
|
|
|
|
|
max = std::max(time, max);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MergeTreeDataPartTTLInfo::update(const MergeTreeDataPartTTLInfo & other_info)
|
|
|
|
{
|
|
|
|
if (other_info.min && (!min || other_info.min < min))
|
|
|
|
min = other_info.min;
|
|
|
|
|
|
|
|
max = std::max(other_info.max, max);
|
|
|
|
if (ttl_finished.has_value())
|
2022-06-07 11:56:03 +00:00
|
|
|
ttl_finished = ttl_finished.value() && other_info.finished();
|
2022-05-26 15:48:08 +00:00
|
|
|
else
|
|
|
|
ttl_finished = other_info.finished();
|
|
|
|
}
|
|
|
|
|
2019-04-15 09:30:45 +00:00
|
|
|
void MergeTreeDataPartTTLInfos::update(const MergeTreeDataPartTTLInfos & other_infos)
|
|
|
|
{
|
|
|
|
for (const auto & [name, ttl_info] : other_infos.columns_ttl)
|
|
|
|
{
|
|
|
|
columns_ttl[name].update(ttl_info);
|
2019-07-28 10:30:46 +00:00
|
|
|
updatePartMinMaxTTL(ttl_info.min, ttl_info.max);
|
2019-04-15 09:30:45 +00:00
|
|
|
}
|
|
|
|
|
2021-01-11 23:07:21 +00:00
|
|
|
for (const auto & [name, ttl_info] : other_infos.rows_where_ttl)
|
|
|
|
{
|
|
|
|
rows_where_ttl[name].update(ttl_info);
|
|
|
|
updatePartMinMaxTTL(ttl_info.min, ttl_info.max);
|
|
|
|
}
|
|
|
|
|
2020-12-25 14:52:46 +00:00
|
|
|
for (const auto & [name, ttl_info] : other_infos.group_by_ttl)
|
|
|
|
{
|
|
|
|
group_by_ttl[name].update(ttl_info);
|
|
|
|
updatePartMinMaxTTL(ttl_info.min, ttl_info.max);
|
|
|
|
}
|
|
|
|
|
2020-08-31 19:50:42 +00:00
|
|
|
for (const auto & [name, ttl_info] : other_infos.recompression_ttl)
|
|
|
|
recompression_ttl[name].update(ttl_info);
|
|
|
|
|
2019-10-17 16:01:28 +00:00
|
|
|
for (const auto & [expression, ttl_info] : other_infos.moves_ttl)
|
|
|
|
moves_ttl[expression].update(ttl_info);
|
2019-11-26 08:02:48 +00:00
|
|
|
|
|
|
|
table_ttl.update(other_infos.table_ttl);
|
|
|
|
updatePartMinMaxTTL(table_ttl.min, table_ttl.max);
|
2019-04-15 09:30:45 +00:00
|
|
|
}
|
|
|
|
|
2019-10-17 16:01:28 +00:00
|
|
|
|
2019-04-15 09:30:45 +00:00
|
|
|
void MergeTreeDataPartTTLInfos::read(ReadBuffer & in)
|
|
|
|
{
|
|
|
|
String json_str;
|
|
|
|
readString(json_str, in);
|
|
|
|
assertEOF(in);
|
|
|
|
|
|
|
|
JSON json(json_str);
|
|
|
|
if (json.has("columns"))
|
|
|
|
{
|
2019-11-11 06:52:38 +00:00
|
|
|
const JSON & columns = json["columns"];
|
2020-03-09 01:50:33 +00:00
|
|
|
for (auto col : columns) // NOLINT
|
2019-04-15 09:30:45 +00:00
|
|
|
{
|
|
|
|
MergeTreeDataPartTTLInfo ttl_info;
|
|
|
|
ttl_info.min = col["min"].getUInt();
|
|
|
|
ttl_info.max = col["max"].getUInt();
|
2021-06-27 16:18:15 +00:00
|
|
|
|
|
|
|
if (col.has("finished"))
|
2022-05-26 15:48:08 +00:00
|
|
|
ttl_info.ttl_finished = col["finished"].getUInt();
|
2021-06-27 16:18:15 +00:00
|
|
|
|
2019-04-15 09:30:45 +00:00
|
|
|
String name = col["name"].getString();
|
|
|
|
columns_ttl.emplace(name, ttl_info);
|
|
|
|
|
2019-07-28 10:30:46 +00:00
|
|
|
updatePartMinMaxTTL(ttl_info.min, ttl_info.max);
|
2019-04-15 09:30:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (json.has("table"))
|
|
|
|
{
|
2019-11-11 06:52:38 +00:00
|
|
|
const JSON & table = json["table"];
|
2019-04-15 09:30:45 +00:00
|
|
|
table_ttl.min = table["min"].getUInt();
|
|
|
|
table_ttl.max = table["max"].getUInt();
|
|
|
|
|
2021-06-27 16:18:15 +00:00
|
|
|
if (table.has("finished"))
|
2022-05-26 15:48:08 +00:00
|
|
|
table_ttl.ttl_finished = table["finished"].getUInt();
|
2021-06-27 16:18:15 +00:00
|
|
|
|
2019-07-28 10:30:46 +00:00
|
|
|
updatePartMinMaxTTL(table_ttl.min, table_ttl.max);
|
2019-04-15 09:30:45 +00:00
|
|
|
}
|
2020-12-25 14:52:46 +00:00
|
|
|
|
2021-01-27 23:20:57 +00:00
|
|
|
auto fill_ttl_info_map = [this](const JSON & json_part, TTLInfoMap & ttl_info_map, bool update_min_max)
|
2019-10-17 16:01:28 +00:00
|
|
|
{
|
2020-12-25 14:52:46 +00:00
|
|
|
for (auto elem : json_part) // NOLINT
|
2019-10-17 16:01:28 +00:00
|
|
|
{
|
|
|
|
MergeTreeDataPartTTLInfo ttl_info;
|
2020-12-25 14:52:46 +00:00
|
|
|
ttl_info.min = elem["min"].getUInt();
|
|
|
|
ttl_info.max = elem["max"].getUInt();
|
2021-06-27 16:18:15 +00:00
|
|
|
|
|
|
|
if (elem.has("finished"))
|
2022-05-26 15:48:08 +00:00
|
|
|
ttl_info.ttl_finished = elem["finished"].getUInt();
|
2021-06-27 16:18:15 +00:00
|
|
|
|
2020-12-25 14:52:46 +00:00
|
|
|
String expression = elem["expression"].getString();
|
|
|
|
ttl_info_map.emplace(expression, ttl_info);
|
2021-01-27 23:20:57 +00:00
|
|
|
|
|
|
|
if (update_min_max)
|
|
|
|
updatePartMinMaxTTL(ttl_info.min, ttl_info.max);
|
2019-10-17 16:01:28 +00:00
|
|
|
}
|
2020-12-25 14:52:46 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
if (json.has("moves"))
|
|
|
|
{
|
|
|
|
const JSON & moves = json["moves"];
|
2021-01-27 23:20:57 +00:00
|
|
|
fill_ttl_info_map(moves, moves_ttl, false);
|
2019-10-17 16:01:28 +00:00
|
|
|
}
|
2020-08-31 13:29:31 +00:00
|
|
|
if (json.has("recompression"))
|
|
|
|
{
|
2020-09-02 16:15:41 +00:00
|
|
|
const JSON & recompressions = json["recompression"];
|
2021-01-27 23:20:57 +00:00
|
|
|
fill_ttl_info_map(recompressions, recompression_ttl, false);
|
2020-12-25 14:52:46 +00:00
|
|
|
}
|
|
|
|
if (json.has("group_by"))
|
|
|
|
{
|
|
|
|
const JSON & group_by = json["group_by"];
|
2021-01-27 23:20:57 +00:00
|
|
|
fill_ttl_info_map(group_by, group_by_ttl, true);
|
2020-08-31 13:29:31 +00:00
|
|
|
}
|
2021-01-11 23:07:21 +00:00
|
|
|
if (json.has("rows_where"))
|
|
|
|
{
|
|
|
|
const JSON & rows_where = json["rows_where"];
|
2021-01-27 23:20:57 +00:00
|
|
|
fill_ttl_info_map(rows_where, rows_where_ttl, true);
|
2021-01-11 23:07:21 +00:00
|
|
|
}
|
2019-04-15 09:30:45 +00:00
|
|
|
}
|
|
|
|
|
2019-10-17 16:01:28 +00:00
|
|
|
|
2019-04-15 09:30:45 +00:00
|
|
|
void MergeTreeDataPartTTLInfos::write(WriteBuffer & out) const
|
|
|
|
{
|
|
|
|
writeString("ttl format version: 1\n", out);
|
|
|
|
writeString("{", out);
|
|
|
|
if (!columns_ttl.empty())
|
|
|
|
{
|
|
|
|
writeString("\"columns\":[", out);
|
|
|
|
for (auto it = columns_ttl.begin(); it != columns_ttl.end(); ++it)
|
|
|
|
{
|
|
|
|
if (it != columns_ttl.begin())
|
|
|
|
writeString(",", out);
|
|
|
|
|
2019-10-17 16:01:28 +00:00
|
|
|
writeString("{\"name\":", out);
|
|
|
|
writeString(doubleQuoteString(it->first), out);
|
|
|
|
writeString(",\"min\":", out);
|
2019-04-15 09:30:45 +00:00
|
|
|
writeIntText(it->second.min, out);
|
|
|
|
writeString(",\"max\":", out);
|
|
|
|
writeIntText(it->second.max, out);
|
2021-06-27 16:18:15 +00:00
|
|
|
writeString(R"(,"finished":)", out);
|
2022-05-26 15:48:08 +00:00
|
|
|
writeIntText(static_cast<uint8_t>(it->second.finished()), out);
|
2019-04-15 09:30:45 +00:00
|
|
|
writeString("}", out);
|
|
|
|
}
|
|
|
|
writeString("]", out);
|
|
|
|
}
|
|
|
|
if (table_ttl.min)
|
|
|
|
{
|
|
|
|
if (!columns_ttl.empty())
|
|
|
|
writeString(",", out);
|
2020-03-09 01:59:08 +00:00
|
|
|
writeString(R"("table":{"min":)", out);
|
2019-04-15 09:30:45 +00:00
|
|
|
writeIntText(table_ttl.min, out);
|
2020-03-09 01:59:08 +00:00
|
|
|
writeString(R"(,"max":)", out);
|
2019-04-15 09:30:45 +00:00
|
|
|
writeIntText(table_ttl.max, out);
|
2021-06-27 16:18:15 +00:00
|
|
|
writeString(R"(,"finished":)", out);
|
2022-05-26 15:48:08 +00:00
|
|
|
writeIntText(static_cast<uint8_t>(table_ttl.finished()), out);
|
2019-04-15 09:30:45 +00:00
|
|
|
writeString("}", out);
|
|
|
|
}
|
2020-12-25 14:52:46 +00:00
|
|
|
|
2021-01-27 16:48:55 +00:00
|
|
|
auto write_infos = [&out](const TTLInfoMap & infos, const String & type, bool is_first)
|
2020-12-25 14:52:46 +00:00
|
|
|
{
|
2021-01-11 23:07:21 +00:00
|
|
|
if (!is_first)
|
2019-10-17 16:01:28 +00:00
|
|
|
writeString(",", out);
|
2021-01-11 23:07:21 +00:00
|
|
|
|
2021-01-12 14:04:03 +00:00
|
|
|
writeDoubleQuotedString(type, out);
|
|
|
|
writeString(":[", out);
|
2021-01-11 23:07:21 +00:00
|
|
|
for (auto it = infos.begin(); it != infos.end(); ++it)
|
2019-10-17 16:01:28 +00:00
|
|
|
{
|
2021-01-11 23:07:21 +00:00
|
|
|
if (it != infos.begin())
|
2019-10-17 16:01:28 +00:00
|
|
|
writeString(",", out);
|
|
|
|
|
2021-01-11 23:07:21 +00:00
|
|
|
writeString(R"({"expression":)", out);
|
|
|
|
writeString(doubleQuoteString(it->first), out);
|
|
|
|
writeString(R"(,"min":)", out);
|
|
|
|
writeIntText(it->second.min, out);
|
|
|
|
writeString(R"(,"max":)", out);
|
|
|
|
writeIntText(it->second.max, out);
|
2021-06-27 16:18:15 +00:00
|
|
|
writeString(R"(,"finished":)", out);
|
2022-05-26 15:48:08 +00:00
|
|
|
writeIntText(static_cast<uint8_t>(it->second.finished()), out);
|
2021-01-11 23:07:21 +00:00
|
|
|
writeString("}", out);
|
2019-10-17 16:01:28 +00:00
|
|
|
}
|
|
|
|
writeString("]", out);
|
2021-01-11 23:07:21 +00:00
|
|
|
};
|
2020-08-31 13:29:31 +00:00
|
|
|
|
2021-01-11 23:07:21 +00:00
|
|
|
bool is_first = columns_ttl.empty() && !table_ttl.min;
|
2021-01-12 14:04:03 +00:00
|
|
|
if (!moves_ttl.empty())
|
|
|
|
{
|
|
|
|
write_infos(moves_ttl, "moves", is_first);
|
|
|
|
is_first = false;
|
|
|
|
}
|
2020-08-31 13:29:31 +00:00
|
|
|
|
2021-01-12 14:04:03 +00:00
|
|
|
if (!recompression_ttl.empty())
|
|
|
|
{
|
|
|
|
write_infos(recompression_ttl, "recompression", is_first);
|
|
|
|
is_first = false;
|
|
|
|
}
|
2020-12-25 14:52:46 +00:00
|
|
|
|
2021-01-12 14:04:03 +00:00
|
|
|
if (!group_by_ttl.empty())
|
|
|
|
{
|
|
|
|
write_infos(group_by_ttl, "group_by", is_first);
|
|
|
|
is_first = false;
|
|
|
|
}
|
2021-01-11 23:07:21 +00:00
|
|
|
|
2021-01-12 14:04:03 +00:00
|
|
|
if (!rows_where_ttl.empty())
|
|
|
|
write_infos(rows_where_ttl, "rows_where", is_first);
|
2020-12-25 14:52:46 +00:00
|
|
|
|
2019-04-15 09:30:45 +00:00
|
|
|
writeString("}", out);
|
|
|
|
}
|
|
|
|
|
2020-09-09 09:15:42 +00:00
|
|
|
time_t MergeTreeDataPartTTLInfos::getMinimalMaxRecompressionTTL() const
|
2020-09-02 10:30:04 +00:00
|
|
|
{
|
2020-09-09 09:15:42 +00:00
|
|
|
time_t max = std::numeric_limits<time_t>::max();
|
2020-09-02 10:30:04 +00:00
|
|
|
for (const auto & [name, info] : recompression_ttl)
|
2020-09-09 09:15:42 +00:00
|
|
|
if (info.max != 0)
|
|
|
|
max = std::min(info.max, max);
|
2020-09-02 10:30:04 +00:00
|
|
|
|
2020-09-09 09:15:42 +00:00
|
|
|
if (max == std::numeric_limits<time_t>::max())
|
2020-09-02 10:30:04 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
return max;
|
|
|
|
}
|
|
|
|
|
2021-06-27 16:18:15 +00:00
|
|
|
bool MergeTreeDataPartTTLInfos::hasAnyNonFinishedTTLs() const
|
|
|
|
{
|
|
|
|
auto has_non_finished_ttl = [] (const TTLInfoMap & map) -> bool
|
|
|
|
{
|
|
|
|
for (const auto & [name, info] : map)
|
|
|
|
{
|
2022-05-26 15:48:08 +00:00
|
|
|
if (!info.finished())
|
2021-06-27 16:18:15 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
2022-05-26 15:48:08 +00:00
|
|
|
if (!table_ttl.finished())
|
2021-06-27 16:18:15 +00:00
|
|
|
return true;
|
|
|
|
|
|
|
|
if (has_non_finished_ttl(columns_ttl))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (has_non_finished_ttl(rows_where_ttl))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (has_non_finished_ttl(moves_ttl))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (has_non_finished_ttl(recompression_ttl))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (has_non_finished_ttl(group_by_ttl))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-09-07 07:59:14 +00:00
|
|
|
std::optional<TTLDescription> selectTTLDescriptionForTTLInfos(const TTLDescriptions & descriptions, const TTLInfoMap & ttl_info_map, time_t current_time, bool use_max)
|
2020-09-02 12:16:12 +00:00
|
|
|
{
|
|
|
|
time_t best_ttl_time = 0;
|
|
|
|
TTLDescriptions::const_iterator best_entry_it;
|
|
|
|
for (auto ttl_entry_it = descriptions.begin(); ttl_entry_it != descriptions.end(); ++ttl_entry_it)
|
|
|
|
{
|
|
|
|
auto ttl_info_it = ttl_info_map.find(ttl_entry_it->result_column);
|
2020-10-05 16:41:46 +00:00
|
|
|
|
|
|
|
if (ttl_info_it == ttl_info_map.end())
|
|
|
|
continue;
|
|
|
|
|
2020-09-02 12:16:12 +00:00
|
|
|
time_t ttl_time;
|
|
|
|
|
|
|
|
if (use_max)
|
|
|
|
ttl_time = ttl_info_it->second.max;
|
|
|
|
else
|
|
|
|
ttl_time = ttl_info_it->second.min;
|
|
|
|
|
|
|
|
/// Prefer TTL rule which went into action last.
|
2020-10-05 16:41:46 +00:00
|
|
|
if (ttl_time <= current_time
|
2020-09-02 12:16:12 +00:00
|
|
|
&& best_ttl_time <= ttl_time)
|
|
|
|
{
|
|
|
|
best_entry_it = ttl_entry_it;
|
|
|
|
best_ttl_time = ttl_time;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return best_ttl_time ? *best_entry_it : std::optional<TTLDescription>();
|
|
|
|
}
|
|
|
|
|
2021-06-27 16:18:15 +00:00
|
|
|
|
2019-04-15 09:30:45 +00:00
|
|
|
}
|