mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 15:12:02 +00:00
dbms: more uniform distribution of work among threads [#METR-2944].
This commit is contained in:
parent
5d19f28d05
commit
ae4c458c5b
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <queue>
|
||||
#include <stack>
|
||||
#include <atomic>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
@ -49,7 +49,7 @@ public:
|
||||
: inputs(inputs_), max_threads(std::min(inputs_.size(), max_threads_)), handler(handler_)
|
||||
{
|
||||
for (size_t i = 0; i < inputs_.size(); ++i)
|
||||
input_queue.emplace(inputs_[i], i);
|
||||
input_stack.emplace(inputs_[i], i);
|
||||
}
|
||||
|
||||
~ParallelInputsProcessor()
|
||||
@ -162,16 +162,16 @@ private:
|
||||
|
||||
/// Выбираем следующий источник.
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(input_queue_mutex);
|
||||
std::lock_guard<std::mutex> lock(input_stack_mutex);
|
||||
|
||||
/// Если свободных источников нет, то этот поток больше не нужен. (Но другие потоки могут работать со своими источниками.)
|
||||
if (input_queue.empty())
|
||||
if (input_stack.empty())
|
||||
break;
|
||||
|
||||
input = input_queue.front();
|
||||
input = input_stack.top();
|
||||
|
||||
/// Убираем источник из очереди доступных источников.
|
||||
input_queue.pop();
|
||||
input_stack.pop();
|
||||
}
|
||||
|
||||
/// Основная работа.
|
||||
@ -183,15 +183,15 @@ private:
|
||||
|
||||
/// Если этот источник ещё не иссяк, то положим полученный блок в очередь готовых.
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(input_queue_mutex);
|
||||
std::lock_guard<std::mutex> lock(input_stack_mutex);
|
||||
|
||||
if (block)
|
||||
{
|
||||
input_queue.push(input);
|
||||
input_stack.push(input);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (input_queue.empty())
|
||||
if (input_stack.empty())
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -214,12 +214,15 @@ private:
|
||||
typedef std::vector<std::thread> ThreadsData;
|
||||
ThreadsData threads;
|
||||
|
||||
/// Очередь доступных источников, которые не заняты каким-либо потоком в данный момент.
|
||||
typedef std::queue<InputData> InputQueue;
|
||||
InputQueue input_queue;
|
||||
/** Стек доступных источников, которые не заняты каким-либо потоком в данный момент.
|
||||
* Стек вместо очереди - чтобы выполнять работу по чтению одного источника более последовательно.
|
||||
* То есть, продолжать обработку источника, который недавно обрабатывался.
|
||||
*/
|
||||
typedef std::stack<InputData> InputStack;
|
||||
InputStack input_stack;
|
||||
|
||||
/// Для операций с input_queue.
|
||||
std::mutex input_queue_mutex;
|
||||
/// Для операций с input_stack.
|
||||
std::mutex input_stack_mutex;
|
||||
|
||||
/// Сколько источников иссякло.
|
||||
std::atomic<size_t> active_threads { 0 };
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include <DB/DataStreams/DistinctBlockInputStream.h>
|
||||
#include <DB/DataStreams/NullBlockInputStream.h>
|
||||
#include <DB/DataStreams/TotalsHavingBlockInputStream.h>
|
||||
#include <DB/DataStreams/narrowBlockInputStreams.h>
|
||||
#include <DB/DataStreams/copyData.h>
|
||||
#include <DB/DataStreams/CreatingSetsBlockInputStream.h>
|
||||
#include <DB/DataStreams/MaterializingBlockInputStream.h>
|
||||
@ -697,12 +696,6 @@ QueryProcessingStage::Enum InterpreterSelectQuery::executeFetchColumns(BlockInpu
|
||||
streams.push_back(interpreter_subquery->execute());
|
||||
}
|
||||
|
||||
/** Если истчоников слишком много, то склеим их в max_threads источников.
|
||||
* (Иначе действия в каждом маленьком источнике, а затем объединение состояний, слишком неэффективно.)
|
||||
*/
|
||||
if (streams.size() > settings.max_threads)
|
||||
streams = narrowBlockInputStreams(streams, settings.max_threads);
|
||||
|
||||
/** Установка ограничений и квоты на чтение данных, скорость и время выполнения запроса.
|
||||
* Такие ограничения проверяются на сервере-инициаторе запроса, а не на удалённых серверах.
|
||||
* Потому что сервер-инициатор имеет суммарные данные о выполнении запроса на всех серверах.
|
||||
|
@ -4,7 +4,6 @@
|
||||
#include <DB/Parsers/ASTIdentifier.h>
|
||||
#include <DB/DataStreams/ExpressionBlockInputStream.h>
|
||||
#include <DB/DataStreams/FilterBlockInputStream.h>
|
||||
#include <DB/DataStreams/ConcatBlockInputStream.h>
|
||||
#include <DB/DataStreams/CollapsingFinalBlockInputStream.h>
|
||||
#include <DB/DataStreams/AddingConstColumnBlockInputStream.h>
|
||||
#include <DB/DataStreams/CreatingSetsBlockInputStream.h>
|
||||
@ -374,7 +373,6 @@ BlockInputStreams MergeTreeDataSelectExecutor::spreadMarkRangesAmongThreads(
|
||||
for (size_t i = 0; i < threads && !parts.empty(); ++i)
|
||||
{
|
||||
size_t need_marks = min_marks_per_thread;
|
||||
BlockInputStreams streams;
|
||||
|
||||
/// Цикл по кускам.
|
||||
while (need_marks > 0 && !parts.empty())
|
||||
@ -427,7 +425,7 @@ BlockInputStreams MergeTreeDataSelectExecutor::spreadMarkRangesAmongThreads(
|
||||
}
|
||||
}
|
||||
|
||||
streams.push_back(new MergeTreeBlockInputStream(
|
||||
res.push_back(new MergeTreeBlockInputStream(
|
||||
data.getFullPath() + part.data_part->name + '/', max_block_size, column_names, data,
|
||||
part.data_part, ranges_to_get_from_part, use_uncompressed_cache,
|
||||
prewhere_actions, prewhere_column));
|
||||
@ -435,18 +433,13 @@ BlockInputStreams MergeTreeDataSelectExecutor::spreadMarkRangesAmongThreads(
|
||||
for (const String & virt_column : virt_columns)
|
||||
{
|
||||
if (virt_column == "_part")
|
||||
streams.back() = new AddingConstColumnBlockInputStream<String>(
|
||||
streams.back(), new DataTypeString, part.data_part->name, "_part");
|
||||
res.back() = new AddingConstColumnBlockInputStream<String>(
|
||||
res.back(), new DataTypeString, part.data_part->name, "_part");
|
||||
else if (virt_column == "_part_index")
|
||||
streams.back() = new AddingConstColumnBlockInputStream<UInt64>(
|
||||
streams.back(), new DataTypeUInt64, part.part_index_in_query, "_part_index");
|
||||
res.back() = new AddingConstColumnBlockInputStream<UInt64>(
|
||||
res.back(), new DataTypeUInt64, part.part_index_in_query, "_part_index");
|
||||
}
|
||||
}
|
||||
|
||||
if (streams.size() == 1)
|
||||
res.push_back(streams[0]);
|
||||
else
|
||||
res.push_back(new ConcatBlockInputStream(streams));
|
||||
}
|
||||
|
||||
if (!parts.empty())
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include <DB/Interpreters/executeQuery.h>
|
||||
#include <DB/Interpreters/InterpreterDropQuery.h>
|
||||
#include <DB/DataStreams/ConcatBlockInputStream.h>
|
||||
#include <DB/DataStreams/narrowBlockInputStreams.h>
|
||||
#include <DB/DataStreams/AddingDefaultBlockInputStream.h>
|
||||
#include <DB/DataStreams/AddingConstColumnBlockInputStream.h>
|
||||
#include <DB/Common/VirtualColumnUtils.h>
|
||||
@ -210,11 +209,6 @@ BlockInputStreams StorageChunkMerger::read(
|
||||
processed_stage = tmp_processed_stage;
|
||||
}
|
||||
|
||||
/** Если истчоников слишком много, то склеим их в threads источников.
|
||||
*/
|
||||
if (res.size() > threads)
|
||||
res = narrowBlockInputStreams(res, threads);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
#include <DB/DataStreams/narrowBlockInputStreams.h>
|
||||
#include <DB/DataStreams/AddingConstColumnBlockInputStream.h>
|
||||
#include <DB/Storages/StorageMerge.h>
|
||||
#include <DB/Common/VirtualColumnUtils.h>
|
||||
@ -173,11 +172,6 @@ BlockInputStreams StorageMerge::read(
|
||||
processed_stage = tmp_processed_stage;
|
||||
}
|
||||
|
||||
/** Если истчоников слишком много, то склеим их в threads источников.
|
||||
*/
|
||||
if (res.size() > threads)
|
||||
res = narrowBlockInputStreams(res, threads);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user