mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-25 00:52:02 +00:00
dbms: sending totals as separate packet [#CONV-8366].
This commit is contained in:
parent
a933ed4e43
commit
c7d8723a54
@ -152,6 +152,9 @@ private:
|
|||||||
SharedPtr<Exception> receiveException();
|
SharedPtr<Exception> receiveException();
|
||||||
Progress receiveProgress();
|
Progress receiveProgress();
|
||||||
BlockStreamProfileInfo receiveProfileInfo();
|
BlockStreamProfileInfo receiveProfileInfo();
|
||||||
|
Block receiveTotals();
|
||||||
|
|
||||||
|
void initBlockInput();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,3 +32,4 @@
|
|||||||
#define DBMS_MIN_REVISION_WITH_PROFILING_PACKET 32029
|
#define DBMS_MIN_REVISION_WITH_PROFILING_PACKET 32029
|
||||||
#define DBMS_MIN_REVISION_WITH_HEADER_BLOCK 32881
|
#define DBMS_MIN_REVISION_WITH_HEADER_BLOCK 32881
|
||||||
#define DBMS_MIN_REVISION_WITH_USER_PASSWORD 34482
|
#define DBMS_MIN_REVISION_WITH_USER_PASSWORD 34482
|
||||||
|
#define DBMS_MIN_REVISION_WITH_TOTALS 35265
|
||||||
|
@ -36,8 +36,9 @@ namespace DB
|
|||||||
* но клиент всё равно должен читать все пакеты до EndOfStream.
|
* но клиент всё равно должен читать все пакеты до EndOfStream.
|
||||||
*
|
*
|
||||||
* Перед пакетом EndOfStream, если есть профайлинговая информация и ревизия клиента достаточно новая,
|
* Перед пакетом EndOfStream, если есть профайлинговая информация и ревизия клиента достаточно новая,
|
||||||
* может быть отправлен пакет ProfileInfo. После него передаются данные профайлинга -
|
* может быть отправлен пакет Totals и/или ProfileInfo.
|
||||||
* сериализованная структура BlockStreamProfileInfo.
|
* Totals - блок с тотальными значениями.
|
||||||
|
* ProfileInfo - данные профайлинга - сериализованная структура BlockStreamProfileInfo.
|
||||||
*
|
*
|
||||||
* При запросах, которые возвращают данные, сервер, перед обработкой запроса,
|
* При запросах, которые возвращают данные, сервер, перед обработкой запроса,
|
||||||
* отправляет заголовочный блок, содержащий описание столбцов из запроса, но с нулем строк.
|
* отправляет заголовочный блок, содержащий описание столбцов из запроса, но с нулем строк.
|
||||||
@ -60,7 +61,8 @@ namespace Protocol
|
|||||||
Progress = 3, /// Прогресс выполнения запроса: строк считано, байт считано.
|
Progress = 3, /// Прогресс выполнения запроса: строк считано, байт считано.
|
||||||
Pong = 4, /// Ответ на Ping.
|
Pong = 4, /// Ответ на Ping.
|
||||||
EndOfStream = 5, /// Все пакеты были переданы.
|
EndOfStream = 5, /// Все пакеты были переданы.
|
||||||
ProfileInfo = 6, /// Пакет с профайлинговой информацией
|
ProfileInfo = 6, /// Пакет с профайлинговой информацией.
|
||||||
|
Totals = 7, /// Блок данных с тотальными значениями, со сжатием или без.
|
||||||
};
|
};
|
||||||
|
|
||||||
/** NOTE: Если бы в качестве типа агрумента функции был бы Enum, то сравнение packet >= 0 && packet < 7
|
/** NOTE: Если бы в качестве типа агрумента функции был бы Enum, то сравнение packet >= 0 && packet < 7
|
||||||
|
@ -122,6 +122,7 @@ public:
|
|||||||
case Protocol::Server::Data:
|
case Protocol::Server::Data:
|
||||||
case Protocol::Server::Progress:
|
case Protocol::Server::Progress:
|
||||||
case Protocol::Server::ProfileInfo:
|
case Protocol::Server::ProfileInfo:
|
||||||
|
case Protocol::Server::Totals:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Protocol::Server::EndOfStream:
|
case Protocol::Server::EndOfStream:
|
||||||
@ -180,6 +181,10 @@ protected:
|
|||||||
case Protocol::Server::ProfileInfo:
|
case Protocol::Server::ProfileInfo:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Protocol::Server::Totals:
|
||||||
|
totals = packet.block;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw Exception("Unknown packet from server", ErrorCodes::UNKNOWN_PACKET_FROM_SERVER);
|
throw Exception("Unknown packet from server", ErrorCodes::UNKNOWN_PACKET_FROM_SERVER);
|
||||||
}
|
}
|
||||||
|
@ -671,6 +671,10 @@ private:
|
|||||||
onProfileInfo(packet.profile_info);
|
onProfileInfo(packet.profile_info);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
case Protocol::Server::Totals:
|
||||||
|
onTotals(packet.block);
|
||||||
|
return true;
|
||||||
|
|
||||||
case Protocol::Server::Exception:
|
case Protocol::Server::Exception:
|
||||||
onException(*packet.exception);
|
onException(*packet.exception);
|
||||||
last_exception = packet.exception;
|
last_exception = packet.exception;
|
||||||
@ -743,13 +747,12 @@ private:
|
|||||||
|
|
||||||
std_out.next();
|
std_out.next();
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
|
||||||
if (block_std_out)
|
|
||||||
block_std_out->writeSuffix();
|
void onTotals(Block & block)
|
||||||
|
{
|
||||||
std_out.next();
|
block_std_out->setTotals(block);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -811,6 +814,11 @@ private:
|
|||||||
|
|
||||||
void onEndOfStream()
|
void onEndOfStream()
|
||||||
{
|
{
|
||||||
|
if (block_std_out)
|
||||||
|
block_std_out->writeSuffix();
|
||||||
|
|
||||||
|
std_out.next();
|
||||||
|
|
||||||
if (is_interactive && !written_first_block)
|
if (is_interactive && !written_first_block)
|
||||||
std::cout << "Ok." << std::endl;
|
std::cout << "Ok." << std::endl;
|
||||||
}
|
}
|
||||||
|
@ -288,6 +288,10 @@ Connection::Packet Connection::receivePacket()
|
|||||||
res.profile_info = receiveProfileInfo();
|
res.profile_info = receiveProfileInfo();
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
|
case Protocol::Server::Totals:
|
||||||
|
res.block = receiveTotals();
|
||||||
|
return res;
|
||||||
|
|
||||||
case Protocol::Server::EndOfStream:
|
case Protocol::Server::EndOfStream:
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
@ -305,6 +309,15 @@ Block Connection::receiveData()
|
|||||||
{
|
{
|
||||||
//LOG_TRACE(log, "Receiving data (" << getServerAddress() << ")");
|
//LOG_TRACE(log, "Receiving data (" << getServerAddress() << ")");
|
||||||
|
|
||||||
|
initBlockInput();
|
||||||
|
|
||||||
|
/// Прочитать из сети один блок
|
||||||
|
return block_in->read();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Connection::initBlockInput()
|
||||||
|
{
|
||||||
if (!block_in)
|
if (!block_in)
|
||||||
{
|
{
|
||||||
if (compression == Protocol::Compression::Enable)
|
if (compression == Protocol::Compression::Enable)
|
||||||
@ -314,9 +327,6 @@ Block Connection::receiveData()
|
|||||||
|
|
||||||
block_in = new NativeBlockInputStream(*maybe_compressed_in, data_type_factory);
|
block_in = new NativeBlockInputStream(*maybe_compressed_in, data_type_factory);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Прочитать из сети один блок
|
|
||||||
return block_in->read();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -353,4 +363,11 @@ BlockStreamProfileInfo Connection::receiveProfileInfo()
|
|||||||
return profile_info;
|
return profile_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Block Connection::receiveTotals()
|
||||||
|
{
|
||||||
|
/// Блок с тотальными значениями передаётся так же, как обычный блок данных. Разница только в идентификаторе пакета.
|
||||||
|
return receiveData();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -239,11 +239,14 @@ void TCPHandler::processOrdinaryQuery()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Если закончились данные, то отправим данные профайлинга до
|
/// Если закончились данные, то отправим данные профайлинга и тотальные значения до
|
||||||
/// последнего нулевого блока, чтобы иметь возможность использовать
|
/// последнего нулевого блока, чтобы иметь возможность использовать
|
||||||
/// эту информацию в выводе суффикса output stream'а
|
/// эту информацию в выводе суффикса output stream'а
|
||||||
if (!block)
|
if (!block)
|
||||||
|
{
|
||||||
|
sendTotals();
|
||||||
sendProfileInfo();
|
sendProfileInfo();
|
||||||
|
}
|
||||||
|
|
||||||
sendData(block);
|
sendData(block);
|
||||||
if (!block)
|
if (!block)
|
||||||
@ -270,6 +273,29 @@ void TCPHandler::sendProfileInfo()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TCPHandler::sendTotals()
|
||||||
|
{
|
||||||
|
if (client_revision < DBMS_MIN_REVISION_WITH_TOTALS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (const IProfilingBlockInputStream * input = dynamic_cast<const IProfilingBlockInputStream *>(&*state.io.in))
|
||||||
|
{
|
||||||
|
const Block & totals = input->getTotals();
|
||||||
|
|
||||||
|
if (totals)
|
||||||
|
{
|
||||||
|
initBlockOutput();
|
||||||
|
|
||||||
|
writeVarUInt(Protocol::Server::Totals, *out);
|
||||||
|
|
||||||
|
state.block_out->write(input->getTotals());
|
||||||
|
state.maybe_compressed_out->next();
|
||||||
|
out->next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void TCPHandler::logProfileInfo(Stopwatch & watch, IBlockInputStream & in)
|
void TCPHandler::logProfileInfo(Stopwatch & watch, IBlockInputStream & in)
|
||||||
{
|
{
|
||||||
/// Выведем информацию о том, сколько считано строк и байт.
|
/// Выведем информацию о том, сколько считано строк и байт.
|
||||||
@ -412,6 +438,22 @@ void TCPHandler::receiveQuery()
|
|||||||
|
|
||||||
|
|
||||||
bool TCPHandler::receiveData()
|
bool TCPHandler::receiveData()
|
||||||
|
{
|
||||||
|
initBlockInput();
|
||||||
|
|
||||||
|
/// Прочитать из сети один блок и засунуть его в state.io.out (данные для INSERT-а)
|
||||||
|
Block block = state.block_in->read();
|
||||||
|
if (block)
|
||||||
|
{
|
||||||
|
state.io.out->write(block);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TCPHandler::initBlockInput()
|
||||||
{
|
{
|
||||||
if (!state.block_in)
|
if (!state.block_in)
|
||||||
{
|
{
|
||||||
@ -425,18 +467,25 @@ bool TCPHandler::receiveData()
|
|||||||
*state.maybe_compressed_in,
|
*state.maybe_compressed_in,
|
||||||
state.io.out_sample,
|
state.io.out_sample,
|
||||||
query_context.getSettingsRef().max_block_size,
|
query_context.getSettingsRef().max_block_size,
|
||||||
query_context.getDataTypeFactory());
|
query_context.getDataTypeFactory());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/// Прочитать из сети один блок и засунуть его в state.io.out (данные для INSERT-а)
|
|
||||||
Block block = state.block_in->read();
|
|
||||||
if (block)
|
void TCPHandler::initBlockOutput()
|
||||||
|
{
|
||||||
|
if (!state.block_out)
|
||||||
{
|
{
|
||||||
state.io.out->write(block);
|
if (state.compression == Protocol::Compression::Enable)
|
||||||
return true;
|
state.maybe_compressed_out = new CompressedWriteBuffer(*out);
|
||||||
|
else
|
||||||
|
state.maybe_compressed_out = out;
|
||||||
|
|
||||||
|
state.block_out = query_context.getFormatFactory().getOutput(
|
||||||
|
"Native",
|
||||||
|
*state.maybe_compressed_out,
|
||||||
|
state.io.in_sample);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -478,18 +527,7 @@ void TCPHandler::sendData(Block & block)
|
|||||||
{
|
{
|
||||||
Poco::ScopedLock<Poco::FastMutex> lock(send_mutex);
|
Poco::ScopedLock<Poco::FastMutex> lock(send_mutex);
|
||||||
|
|
||||||
if (!state.block_out)
|
initBlockOutput();
|
||||||
{
|
|
||||||
if (state.compression == Protocol::Compression::Enable)
|
|
||||||
state.maybe_compressed_out = new CompressedWriteBuffer(*out);
|
|
||||||
else
|
|
||||||
state.maybe_compressed_out = out;
|
|
||||||
|
|
||||||
state.block_out = query_context.getFormatFactory().getOutput(
|
|
||||||
"Native",
|
|
||||||
*state.maybe_compressed_out,
|
|
||||||
state.io.in_sample);
|
|
||||||
}
|
|
||||||
|
|
||||||
writeVarUInt(Protocol::Server::Data, *out);
|
writeVarUInt(Protocol::Server::Data, *out);
|
||||||
|
|
||||||
|
@ -121,6 +121,11 @@ private:
|
|||||||
void sendProgress(size_t rows, size_t bytes);
|
void sendProgress(size_t rows, size_t bytes);
|
||||||
void sendEndOfStream();
|
void sendEndOfStream();
|
||||||
void sendProfileInfo();
|
void sendProfileInfo();
|
||||||
|
void sendTotals();
|
||||||
|
|
||||||
|
/// Создаёт state.block_in/block_out для чтения/записи блоков, в зависимости от того, включено ли сжатие.
|
||||||
|
void initBlockInput();
|
||||||
|
void initBlockOutput();
|
||||||
|
|
||||||
bool isQueryCancelled();
|
bool isQueryCancelled();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user