ClickHouse/dbms/include/DB/Storages/MergeTree/MergeTreeDataMerger.h

89 lines
3.8 KiB
C
Raw Normal View History

2014-03-13 12:48:07 +00:00
#pragma once
#include <DB/Storages/MergeTree/MergeTreeData.h>
2014-08-04 11:41:59 +00:00
#include <DB/Storages/MergeTree/DiskSpaceMonitor.h>
#include <atomic>
2014-03-13 12:48:07 +00:00
namespace DB
{
2015-04-16 06:12:35 +00:00
class MergeListEntry;
2014-03-13 12:48:07 +00:00
/** Умеет выбирать куски для слияния и сливать их.
*/
class MergeTreeDataMerger
{
public:
2014-05-14 17:51:37 +00:00
static const size_t NO_LIMIT = std::numeric_limits<size_t>::max();
MergeTreeDataMerger(MergeTreeData & data_) : data(data_), log(&Logger::get(data.getLogName() + " (Merger)")) {}
2014-03-13 12:48:07 +00:00
2014-04-04 10:37:33 +00:00
typedef std::function<bool (const MergeTreeData::DataPartPtr &, const MergeTreeData::DataPartPtr &)> AllowedMergingPredicate;
2014-03-13 17:44:00 +00:00
/** Выбирает, какие куски слить. Использует кучу эвристик.
* Если merge_anything_for_old_months, для кусков за прошедшие месяцы снимается ограничение на соотношение размеров.
2014-05-14 17:51:37 +00:00
* Выбирает куски так, чтобы available_disk_space, скорее всего, хватило с запасом для их слияния.
2014-03-13 17:44:00 +00:00
*
* can_merge - функция, определяющая, можно ли объединить пару соседних кусков.
* Эта функция должна координировать слияния со вставками и другими слияниями, обеспечивая, что:
* - Куски, между которыми еще может появиться новый кусок, нельзя сливать. См. METR-7001.
* - Кусок, который уже сливается с кем-то в одном месте, нельзя начать сливать в кем-то другим в другом месте.
*/
2014-03-13 12:48:07 +00:00
bool selectPartsToMerge(
MergeTreeData::DataPartsVector & what,
2014-04-04 10:37:33 +00:00
String & merged_name,
2014-03-13 12:48:07 +00:00
size_t available_disk_space,
bool merge_anything_for_old_months,
2014-03-13 17:44:00 +00:00
bool aggressive,
bool only_small,
const AllowedMergingPredicate & can_merge);
2014-03-13 12:48:07 +00:00
2014-08-04 11:41:59 +00:00
/** Сливает куски.
* Если reservation != nullptr, то и дело уменьшает размер зарезервированного места
* приблизительно пропорционально количеству уже выписанных данных.
*/
2014-07-01 15:58:25 +00:00
MergeTreeData::DataPartPtr mergeParts(
2015-04-16 06:12:35 +00:00
const MergeTreeData::DataPartsVector & parts, const String & merged_name, MergeListEntry & merge_entry,
size_t aio_threshold, MergeTreeData::Transaction * out_transaction = nullptr,
DiskSpaceMonitor::Reservation * disk_reservation = nullptr);
2014-03-13 12:48:07 +00:00
/// Примерное количество места на диске, нужное для мерджа. С запасом.
2015-06-11 00:35:36 +00:00
static size_t estimateDiskSpaceForMerge(const MergeTreeData::DataPartsVector & parts);
2014-03-13 12:48:07 +00:00
2014-05-13 10:10:26 +00:00
/** Отменяет все мерджи. Все выполняющиеся сейчас вызовы mergeParts скоро бросят исключение.
* Все новые вызовы будут бросать исключения, пока не будет вызван uncancelAll().
2014-03-13 12:48:07 +00:00
*/
bool cancelAll() { return canceled.exchange(true, std::memory_order_relaxed); }
bool uncancelAll() { return canceled.exchange(false, std::memory_order_relaxed); }
2014-05-13 10:10:26 +00:00
2014-03-13 12:48:07 +00:00
private:
MergeTreeData & data;
Logger * log;
2014-05-21 10:20:41 +00:00
/// Когда в последний раз писали в лог, что место на диске кончилось (чтобы не писать об этом слишком часто).
time_t disk_space_warning_time = 0;
std::atomic<bool> canceled{false};
};
class MergeTreeMergeBlocker
{
public:
MergeTreeMergeBlocker(MergeTreeDataMerger & merger)
2014-12-19 14:17:44 +00:00
: merger(merger), was_cancelled{!merger.cancelAll()} {}
~MergeTreeMergeBlocker()
{
if (was_cancelled)
merger.uncancelAll();
}
private:
MergeTreeDataMerger & merger;
const bool was_cancelled;
2014-03-13 12:48:07 +00:00
};
}