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>
|
2014-12-17 11:50:24 +00:00
|
|
|
|
#include <atomic>
|
2016-03-01 17:47:53 +00:00
|
|
|
|
#include <functional>
|
2014-03-13 12:48:07 +00:00
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
|
{
|
|
|
|
|
|
2015-04-16 06:12:35 +00:00
|
|
|
|
class MergeListEntry;
|
2016-11-03 12:00:44 +00:00
|
|
|
|
class MergeProgressCallback;
|
2016-03-07 04:35:06 +00:00
|
|
|
|
struct ReshardingJob;
|
2015-04-16 06:12:35 +00:00
|
|
|
|
|
|
|
|
|
|
2014-03-13 12:48:07 +00:00
|
|
|
|
/** Умеет выбирать куски для слияния и сливать их.
|
|
|
|
|
*/
|
|
|
|
|
class MergeTreeDataMerger
|
|
|
|
|
{
|
2016-03-01 17:47:53 +00:00
|
|
|
|
public:
|
|
|
|
|
using CancellationHook = std::function<void()>;
|
|
|
|
|
using AllowedMergingPredicate = std::function<bool (const MergeTreeData::DataPartPtr &, const MergeTreeData::DataPartPtr &)>;
|
|
|
|
|
|
2014-03-13 12:48:07 +00:00
|
|
|
|
public:
|
2016-11-22 19:27:45 +00:00
|
|
|
|
MergeTreeDataMerger(MergeTreeData & data_, const BackgroundProcessingPool & pool_);
|
2014-03-13 12:48:07 +00:00
|
|
|
|
|
2016-03-01 17:47:53 +00:00
|
|
|
|
void setCancellationHook(CancellationHook cancellation_hook_);
|
2014-03-13 17:44:00 +00:00
|
|
|
|
|
2016-10-27 22:50:02 +00:00
|
|
|
|
/** Get maximum total size of parts to do merge, at current moment of time.
|
|
|
|
|
* It depends on number of free threads in background_pool and amount of free space in disk.
|
|
|
|
|
*/
|
|
|
|
|
size_t getMaxPartsSizeForMerge();
|
|
|
|
|
|
2016-11-24 22:41:27 +00:00
|
|
|
|
/** For explicitly passed size of pool and number of used tasks.
|
|
|
|
|
* This method could be used to calculate threshold depending on number of tasks in replication queue.
|
|
|
|
|
*/
|
|
|
|
|
size_t getMaxPartsSizeForMerge(size_t pool_size, size_t pool_used);
|
|
|
|
|
|
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 17:44:00 +00:00
|
|
|
|
bool aggressive,
|
2016-10-27 22:50:02 +00:00
|
|
|
|
size_t max_total_size_to_merge,
|
2014-03-13 17:44:00 +00:00
|
|
|
|
const AllowedMergingPredicate & can_merge);
|
2014-03-13 12:48:07 +00:00
|
|
|
|
|
2016-05-16 18:43:38 +00:00
|
|
|
|
/** Выбрать для слияния все куски в заданной партиции, если возможно.
|
|
|
|
|
* final - выбирать для слияния даже единственный кусок - то есть, позволять мерджить один кусок "сам с собой".
|
|
|
|
|
*/
|
|
|
|
|
bool selectAllPartsToMergeWithinPartition(
|
|
|
|
|
MergeTreeData::DataPartsVector & what,
|
|
|
|
|
String & merged_name,
|
|
|
|
|
size_t available_disk_space,
|
|
|
|
|
const AllowedMergingPredicate & can_merge,
|
|
|
|
|
DayNum_t partition,
|
|
|
|
|
bool final);
|
|
|
|
|
|
2014-08-04 11:41:59 +00:00
|
|
|
|
/** Сливает куски.
|
|
|
|
|
* Если reservation != nullptr, то и дело уменьшает размер зарезервированного места
|
|
|
|
|
* приблизительно пропорционально количеству уже выписанных данных.
|
2016-03-31 01:25:16 +00:00
|
|
|
|
*
|
|
|
|
|
* Создаёт и возвращает временный кусок.
|
|
|
|
|
* Чтобы закончить мердж, вызовите функцию renameTemporaryMergedPart.
|
2016-04-24 09:44:47 +00:00
|
|
|
|
*
|
|
|
|
|
* time_of_merge - время, когда мердж был назначен.
|
|
|
|
|
* Важно при использовании ReplicatedGraphiteMergeTree для обеспечения одинакового мерджа на репликах.
|
2014-08-04 11:41:59 +00:00
|
|
|
|
*/
|
2016-03-31 01:25:16 +00:00
|
|
|
|
MergeTreeData::MutableDataPartPtr mergePartsToTemporaryPart(
|
2016-03-25 11:48:45 +00:00
|
|
|
|
MergeTreeData::DataPartsVector & parts, const String & merged_name, MergeListEntry & merge_entry,
|
2016-04-24 09:44:47 +00:00
|
|
|
|
size_t aio_threshold, time_t time_of_merge, DiskSpaceMonitor::Reservation * disk_reservation = nullptr);
|
2016-03-31 01:25:16 +00:00
|
|
|
|
|
|
|
|
|
MergeTreeData::DataPartPtr renameMergedTemporaryPart(
|
|
|
|
|
MergeTreeData::DataPartsVector & parts,
|
|
|
|
|
MergeTreeData::MutableDataPartPtr & new_data_part,
|
|
|
|
|
const String & merged_name,
|
2016-10-24 02:06:52 +00:00
|
|
|
|
MergeTreeData::Transaction * out_transaction = nullptr);
|
2014-03-13 12:48:07 +00:00
|
|
|
|
|
2016-01-28 16:06:57 +00:00
|
|
|
|
/** Перешардирует заданную партицию.
|
|
|
|
|
*/
|
|
|
|
|
MergeTreeData::PerShardDataParts reshardPartition(
|
|
|
|
|
const ReshardingJob & job,
|
|
|
|
|
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
|
|
|
|
|
2016-01-28 16:06:57 +00:00
|
|
|
|
private:
|
|
|
|
|
/** Выбрать все куски принадлежащие одной партиции.
|
|
|
|
|
*/
|
|
|
|
|
MergeTreeData::DataPartsVector selectAllPartsFromPartition(DayNum_t partition);
|
2016-03-25 11:48:45 +00:00
|
|
|
|
|
2016-08-26 19:50:04 +00:00
|
|
|
|
/** Temporarily cancel merges.
|
|
|
|
|
*/
|
|
|
|
|
class BlockerImpl
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
BlockerImpl(MergeTreeDataMerger * merger_) : merger(merger_)
|
|
|
|
|
{
|
|
|
|
|
++merger->cancelled;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
~BlockerImpl()
|
|
|
|
|
{
|
|
|
|
|
--merger->cancelled;
|
|
|
|
|
}
|
|
|
|
|
private:
|
|
|
|
|
MergeTreeDataMerger * merger;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
/** Cancel all merges. All currently running 'mergeParts' methods will throw exception soon.
|
|
|
|
|
* All new calls to 'mergeParts' will throw exception till all 'Blocker' objects will be destroyed.
|
|
|
|
|
*/
|
|
|
|
|
using Blocker = std::unique_ptr<BlockerImpl>;
|
|
|
|
|
Blocker cancel() { return std::make_unique<BlockerImpl>(this); }
|
|
|
|
|
|
|
|
|
|
/** Cancel all merges forever.
|
|
|
|
|
*/
|
|
|
|
|
void cancelForever() { ++cancelled; }
|
|
|
|
|
|
|
|
|
|
bool isCancelled() const { return cancelled > 0; }
|
2016-01-28 16:06:57 +00:00
|
|
|
|
|
2016-11-03 12:00:44 +00:00
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
enum class MergeAlgorithm
|
|
|
|
|
{
|
|
|
|
|
Horizontal, /// per-row merge of all columns
|
|
|
|
|
Vertical /// per-row merge of PK columns, per-column gather for non-PK columns
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
|
|
MergeAlgorithm chooseMergeAlgorithm(const MergeTreeData & data, const MergeTreeData::DataPartsVector & parts,
|
2016-12-21 19:00:25 +00:00
|
|
|
|
size_t rows_upper_bound, const NamesAndTypesList & gathering_columns, MergedRowSources & rows_sources_to_alloc) const;
|
2016-11-03 12:00:44 +00:00
|
|
|
|
|
2014-03-13 12:48:07 +00:00
|
|
|
|
private:
|
|
|
|
|
MergeTreeData & data;
|
2016-11-22 19:27:45 +00:00
|
|
|
|
const BackgroundProcessingPool & pool;
|
2014-03-13 12:48:07 +00:00
|
|
|
|
|
|
|
|
|
Logger * log;
|
|
|
|
|
|
2014-05-21 10:20:41 +00:00
|
|
|
|
/// Когда в последний раз писали в лог, что место на диске кончилось (чтобы не писать об этом слишком часто).
|
|
|
|
|
time_t disk_space_warning_time = 0;
|
|
|
|
|
|
2016-03-01 17:47:53 +00:00
|
|
|
|
CancellationHook cancellation_hook;
|
|
|
|
|
|
2016-08-26 19:50:04 +00:00
|
|
|
|
std::atomic<int> cancelled {0};
|
2015-11-06 17:34:48 +00:00
|
|
|
|
|
2016-08-26 19:50:04 +00:00
|
|
|
|
void abortReshardPartitionIfRequested();
|
2014-03-13 12:48:07 +00:00
|
|
|
|
};
|
|
|
|
|
|
2016-08-26 19:50:04 +00:00
|
|
|
|
|
2014-03-13 12:48:07 +00:00
|
|
|
|
}
|