2011-08-27 22:43:31 +00:00
|
|
|
|
#pragma once
|
|
|
|
|
|
2014-10-25 18:33:52 +00:00
|
|
|
|
#include <DB/Core/Progress.h>
|
2011-09-05 00:51:25 +00:00
|
|
|
|
|
2012-12-25 17:25:44 +00:00
|
|
|
|
#include <DB/Interpreters/Limits.h>
|
|
|
|
|
|
2015-01-18 08:25:56 +00:00
|
|
|
|
#include <DB/DataStreams/BlockStreamProfileInfo.h>
|
2011-08-27 22:43:31 +00:00
|
|
|
|
#include <DB/DataStreams/IBlockInputStream.h>
|
|
|
|
|
|
2015-03-20 16:20:47 +00:00
|
|
|
|
#include <atomic>
|
2011-08-27 22:43:31 +00:00
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
|
{
|
|
|
|
|
|
2015-05-29 21:32:10 +00:00
|
|
|
|
class QuotaForIntervals;
|
2015-06-21 06:06:04 +00:00
|
|
|
|
class ProcessListElement;
|
2015-05-29 21:32:10 +00:00
|
|
|
|
|
2011-08-27 22:43:31 +00:00
|
|
|
|
|
2012-05-09 08:16:09 +00:00
|
|
|
|
/** Смотрит за тем, как работает источник блоков.
|
2011-08-27 22:43:31 +00:00
|
|
|
|
* Позволяет получить информацию для профайлинга:
|
|
|
|
|
* строк в секунду, блоков в секунду, мегабайт в секунду и т. п.
|
2012-05-09 08:16:09 +00:00
|
|
|
|
* Позволяет остановить чтение данных (во вложенных источниках).
|
2011-08-27 22:43:31 +00:00
|
|
|
|
*/
|
2011-09-04 21:23:19 +00:00
|
|
|
|
class IProfilingBlockInputStream : public IBlockInputStream
|
2011-08-27 22:43:31 +00:00
|
|
|
|
{
|
|
|
|
|
public:
|
2015-01-18 08:25:56 +00:00
|
|
|
|
Block read() override final;
|
2011-09-04 21:23:19 +00:00
|
|
|
|
|
2013-12-27 13:22:32 +00:00
|
|
|
|
/** Реализация по-умолчанию вызывает рекурсивно readSuffix() у всех детей, а затем readSuffixImpl() у себя.
|
|
|
|
|
* Если этот поток вызывает у детей read() в отдельном потоке, этот поведение обычно неверно:
|
|
|
|
|
* readSuffix() у ребенка нельзя вызывать в момент, когда read() того же ребенка выполняется в другом потоке.
|
|
|
|
|
* В таком случае нужно переопределить этот метод, чтобы readSuffix() у детей вызывался, например, после соединения потоков.
|
|
|
|
|
*/
|
2014-11-08 23:52:18 +00:00
|
|
|
|
void readSuffix() override;
|
2013-09-13 20:33:09 +00:00
|
|
|
|
|
2012-08-23 23:49:28 +00:00
|
|
|
|
/// Получить информацию о скорости выполнения.
|
2014-09-12 16:05:29 +00:00
|
|
|
|
const BlockStreamProfileInfo & getInfo() const { return info; }
|
2011-08-27 22:43:31 +00:00
|
|
|
|
|
2013-09-08 08:27:06 +00:00
|
|
|
|
/** Получить "тотальные" значения.
|
|
|
|
|
* Реализация по-умолчанию берёт их из себя или из первого дочернего источника, в котором они есть.
|
|
|
|
|
* Переопределённый метод может провести некоторые вычисления. Например, применить выражение к totals дочернего источника.
|
|
|
|
|
* Тотальных значений может не быть - тогда возвращается пустой блок.
|
2015-02-04 05:05:17 +00:00
|
|
|
|
*
|
|
|
|
|
* Вызывайте этот метод только после получения всех данных с помощью read,
|
|
|
|
|
* иначе будут проблемы, если какие-то данные в это же время вычисляются в другом потоке.
|
2013-09-08 08:27:06 +00:00
|
|
|
|
*/
|
|
|
|
|
virtual const Block & getTotals();
|
2014-09-12 16:05:29 +00:00
|
|
|
|
|
2013-09-07 02:03:13 +00:00
|
|
|
|
/// То же самое для минимумов и максимумов.
|
|
|
|
|
const Block & getExtremes() const;
|
2013-09-01 04:55:41 +00:00
|
|
|
|
|
2012-10-20 05:54:35 +00:00
|
|
|
|
|
2012-10-18 19:24:46 +00:00
|
|
|
|
/** Установить колбэк прогресса выполнения.
|
2013-11-03 05:32:42 +00:00
|
|
|
|
* Колбэк пробрасывается во все дочерние источники.
|
2012-10-18 19:24:46 +00:00
|
|
|
|
* По-умолчанию, он вызывается для листовых источников, после каждого блока.
|
|
|
|
|
* (Но это может быть переопределено в методе progress())
|
|
|
|
|
* Функция принимает количество строк в последнем блоке, количество байт в последнем блоке.
|
|
|
|
|
* Следует иметь ввиду, что колбэк может вызываться из разных потоков.
|
|
|
|
|
*/
|
|
|
|
|
void setProgressCallback(ProgressCallback callback);
|
|
|
|
|
|
2013-11-03 05:32:42 +00:00
|
|
|
|
|
|
|
|
|
/** В этом методе:
|
|
|
|
|
* - вызывается колбэк прогресса;
|
|
|
|
|
* - обновляется статус выполнения запроса в ProcessList-е;
|
|
|
|
|
* - проверяются ограничения и квоты, которые должны быть проверены не в рамках одного источника,
|
|
|
|
|
* а над общим количеством потраченных ресурсов во всех источниках сразу (информация в ProcessList-е).
|
|
|
|
|
*/
|
2015-02-15 06:08:31 +00:00
|
|
|
|
virtual void progress(const Progress & value)
|
|
|
|
|
{
|
|
|
|
|
/// Данные для прогресса берутся из листовых источников.
|
|
|
|
|
if (children.empty())
|
|
|
|
|
progressImpl(value);
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-25 18:33:52 +00:00
|
|
|
|
void progressImpl(const Progress & value);
|
2013-11-03 05:32:42 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Установить указатель на элемент списка процессов.
|
|
|
|
|
* Пробрасывается во все дочерние источники.
|
|
|
|
|
* В него будет записываться общая информация о потраченных на запрос ресурсах.
|
|
|
|
|
* На основе этой информации будет проверяться квота, и некоторые ограничения.
|
|
|
|
|
* Также эта информация будет доступна в запросе SHOW PROCESSLIST.
|
|
|
|
|
*/
|
2015-06-21 06:06:04 +00:00
|
|
|
|
void setProcessListElement(ProcessListElement * elem);
|
2012-10-18 19:24:46 +00:00
|
|
|
|
|
2015-02-15 06:08:31 +00:00
|
|
|
|
/** Установить информацию о приблизительном общем количестве строк, которых нужно прочитать.
|
|
|
|
|
*/
|
|
|
|
|
void setTotalRowsApprox(size_t value) { total_rows_approx = value; }
|
|
|
|
|
|
2012-10-18 19:24:46 +00:00
|
|
|
|
|
2012-10-17 19:55:56 +00:00
|
|
|
|
/** Попросить прервать получение данных как можно скорее.
|
|
|
|
|
* По-умолчанию - просто выставляет флаг is_cancelled и просит прерваться всех детей.
|
2012-11-10 05:13:46 +00:00
|
|
|
|
* Эта функция может вызываться несколько раз, в том числе, одновременно из разных потоков.
|
2012-10-17 19:55:56 +00:00
|
|
|
|
*/
|
|
|
|
|
virtual void cancel();
|
|
|
|
|
|
2012-10-18 19:24:46 +00:00
|
|
|
|
/** Требуется ли прервать получение данных.
|
2012-10-20 05:54:35 +00:00
|
|
|
|
*/
|
2015-03-20 16:20:47 +00:00
|
|
|
|
bool isCancelled() const
|
2012-10-18 19:24:46 +00:00
|
|
|
|
{
|
2015-03-20 16:20:47 +00:00
|
|
|
|
return is_cancelled.load(std::memory_order_seq_cst);
|
2012-10-18 19:24:46 +00:00
|
|
|
|
}
|
2012-05-17 19:15:53 +00:00
|
|
|
|
|
2013-11-12 23:15:09 +00:00
|
|
|
|
/** Какие ограничения (и квоты) проверяются.
|
|
|
|
|
* Если LIMITS_CURRENT - ограничения проверяются на количество данных, прочитанных только в этом stream-е.
|
|
|
|
|
* - используется для реализации ограничений на объём результата выполнения запроса.
|
|
|
|
|
* Если LIMITS_TOTAL, то ещё дополнительно делается проверка в колбэке прогресса,
|
|
|
|
|
* по суммарным данным по всем листовым stream-ам, в том числе, с удалённых серверов.
|
|
|
|
|
* - используется для реализации ограничений на общий объём прочитанных (исходных) данных.
|
|
|
|
|
*/
|
|
|
|
|
enum LimitsMode
|
|
|
|
|
{
|
|
|
|
|
LIMITS_CURRENT,
|
|
|
|
|
LIMITS_TOTAL,
|
|
|
|
|
};
|
|
|
|
|
|
2012-12-25 17:25:44 +00:00
|
|
|
|
/// Используется подмножество ограничений из Limits.
|
|
|
|
|
struct LocalLimits
|
|
|
|
|
{
|
2015-03-13 21:01:04 +00:00
|
|
|
|
LimitsMode mode = LIMITS_CURRENT;
|
2014-09-12 16:05:29 +00:00
|
|
|
|
|
2015-03-13 21:01:04 +00:00
|
|
|
|
size_t max_rows_to_read = 0;
|
|
|
|
|
size_t max_bytes_to_read = 0;
|
|
|
|
|
OverflowMode read_overflow_mode = OverflowMode::THROW;
|
2012-12-25 17:25:44 +00:00
|
|
|
|
|
2015-03-13 21:01:04 +00:00
|
|
|
|
Poco::Timespan max_execution_time = 0;
|
|
|
|
|
OverflowMode timeout_overflow_mode = OverflowMode::THROW;
|
2012-12-25 17:25:44 +00:00
|
|
|
|
|
|
|
|
|
/// В строчках в секунду.
|
2015-03-13 21:01:04 +00:00
|
|
|
|
size_t min_execution_speed = 0;
|
2012-12-25 17:25:44 +00:00
|
|
|
|
/// Проверять, что скорость не слишком низкая, после прошествия указанного времени.
|
2015-03-13 21:01:04 +00:00
|
|
|
|
Poco::Timespan timeout_before_checking_execution_speed = 0;
|
2012-12-25 17:25:44 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/** Установить ограничения для проверки на каждый блок. */
|
|
|
|
|
void setLimits(const LocalLimits & limits_)
|
|
|
|
|
{
|
|
|
|
|
limits = limits_;
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-12 23:15:09 +00:00
|
|
|
|
/** Установить квоту. Если устанавливается квота на объём исходных данных,
|
|
|
|
|
* то следует ещё установить mode = LIMITS_TOTAL в LocalLimits с помощью setLimits.
|
|
|
|
|
*/
|
|
|
|
|
void setQuota(QuotaForIntervals & quota_)
|
2013-08-28 20:47:22 +00:00
|
|
|
|
{
|
|
|
|
|
quota = "a_;
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-07 02:03:13 +00:00
|
|
|
|
/// Включить рассчёт минимумов и максимумов по столбцам результата.
|
|
|
|
|
void enableExtremes() { enabled_extremes = true; }
|
|
|
|
|
|
2012-05-21 20:38:34 +00:00
|
|
|
|
protected:
|
2011-08-27 22:43:31 +00:00
|
|
|
|
BlockStreamProfileInfo info;
|
2015-03-20 16:20:47 +00:00
|
|
|
|
std::atomic<bool> is_cancelled{false};
|
2012-05-09 15:15:45 +00:00
|
|
|
|
ProgressCallback progress_callback;
|
2015-06-21 06:06:04 +00:00
|
|
|
|
ProcessListElement * process_list_elem = nullptr;
|
2012-10-20 02:10:47 +00:00
|
|
|
|
|
2014-04-08 07:31:51 +00:00
|
|
|
|
bool enabled_extremes = false;
|
2013-09-07 02:03:13 +00:00
|
|
|
|
|
2013-09-01 04:55:41 +00:00
|
|
|
|
/// Дополнительная информация, которая может образоваться в процессе работы.
|
|
|
|
|
|
|
|
|
|
/// Тотальные значения при агрегации.
|
|
|
|
|
Block totals;
|
2013-09-07 02:03:13 +00:00
|
|
|
|
/// Минимумы и максимумы. Первая строчка блока - минимумы, вторая - максимумы.
|
|
|
|
|
Block extremes;
|
2015-02-15 06:08:31 +00:00
|
|
|
|
/// Приблизительное общее количество строк, которых нужно прочитать. Для прогресс-бара.
|
|
|
|
|
size_t total_rows_approx = 0;
|
|
|
|
|
/// Информация о приблизительном общем количестве строк собрана в родительском источнике.
|
|
|
|
|
bool collected_total_rows_approx = false;
|
2013-09-01 04:55:41 +00:00
|
|
|
|
|
2015-11-03 18:58:43 +00:00
|
|
|
|
/// Превышено ограничение на количество строк/байт, и нужно прекратить выполнение на следующем вызове read, как будто поток иссяк.
|
|
|
|
|
bool limit_exceeded_need_break = false;
|
|
|
|
|
|
2013-09-01 04:55:41 +00:00
|
|
|
|
/// Ограничения и квоты.
|
2014-09-12 16:05:29 +00:00
|
|
|
|
|
2012-12-25 17:25:44 +00:00
|
|
|
|
LocalLimits limits;
|
|
|
|
|
|
2014-04-08 07:31:51 +00:00
|
|
|
|
QuotaForIntervals * quota = nullptr; /// Если nullptr - квота не используется.
|
|
|
|
|
double prev_elapsed = 0;
|
2013-08-28 20:47:22 +00:00
|
|
|
|
|
2012-10-20 02:10:47 +00:00
|
|
|
|
/// Наследники должны реализовать эту функцию.
|
|
|
|
|
virtual Block readImpl() = 0;
|
2013-09-07 02:03:13 +00:00
|
|
|
|
|
2013-09-13 20:33:09 +00:00
|
|
|
|
/// Здесь необходимо делать финализацию, которая может привести к исключению.
|
|
|
|
|
virtual void readSuffixImpl() {}
|
2013-09-07 02:03:13 +00:00
|
|
|
|
|
|
|
|
|
void updateExtremes(Block & block);
|
2013-11-03 05:32:42 +00:00
|
|
|
|
|
|
|
|
|
/** Проверить ограничения и квоты.
|
|
|
|
|
* Но только те, что могут быть проверены в рамках каждого отдельного источника.
|
|
|
|
|
*/
|
2013-09-07 02:03:13 +00:00
|
|
|
|
bool checkLimits();
|
|
|
|
|
void checkQuota(Block & block);
|
2015-02-15 06:08:31 +00:00
|
|
|
|
|
|
|
|
|
/// Собрать информацию о приблизительном общем числе строк по всем детям.
|
|
|
|
|
void collectTotalRowsApprox();
|
|
|
|
|
|
|
|
|
|
/** Передать информацию о приблизительном общем числе строк в колбэк прогресса.
|
|
|
|
|
* Сделано так, что отправка происходит лишь в верхнем источнике.
|
|
|
|
|
*/
|
|
|
|
|
void collectAndSendTotalRowsApprox();
|
2011-08-27 22:43:31 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
}
|