ClickHouse/dbms/src/Storages/MergeTree/MergeTreeReaderCompact.cpp

231 lines
8.8 KiB
C++
Raw Normal View History

2019-10-11 15:37:16 +00:00
#include <Storages/MergeTree/MergeTreeReaderCompact.h>
#include <Poco/File.h>
namespace DB
{
2019-10-16 18:27:53 +00:00
namespace ErrorCodes
{
extern const int LOGICAL_ERROR;
extern const int NOT_FOUND_EXPECTED_DATA_PART;
extern const int MEMORY_LIMIT_EXCEEDED;
extern const int ARGUMENT_OUT_OF_BOUND;
}
2019-10-11 15:37:16 +00:00
MergeTreeReaderCompact::MergeTreeReaderCompact(const MergeTreeData::DataPartPtr & data_part_,
const NamesAndTypesList & columns_, UncompressedCache * uncompressed_cache_, MarkCache * mark_cache_,
const MarkRanges & mark_ranges_, const ReaderSettings & settings_, const ValueSizeMap & avg_value_size_hints_)
: IMergeTreeReader(data_part_, columns_
, uncompressed_cache_, mark_cache_, mark_ranges_
, settings_, avg_value_size_hints_)
{
2019-11-20 13:33:41 +00:00
initMarksLoader();
2019-10-16 18:27:53 +00:00
size_t buffer_size = settings.max_read_buffer_size;
if (uncompressed_cache)
{
auto buffer = std::make_unique<CachedCompressedReadBuffer>(
2019-10-31 14:44:17 +00:00
path + "data.bin", uncompressed_cache, 0, settings.min_bytes_to_use_direct_io, buffer_size);
2019-10-16 18:27:53 +00:00
// if (profile_callback)
// buffer->setProfileCallback(profile_callback, clock_type);
cached_buffer = std::move(buffer);
data_buffer = cached_buffer.get();
}
else
{
auto buffer = std::make_unique<CompressedReadBufferFromFile>(
2019-10-31 14:44:17 +00:00
path + "data.bin", 0, settings.min_bytes_to_use_direct_io, buffer_size);
2019-10-16 18:27:53 +00:00
// if (profile_callback)
// buffer->setProfileCallback(profile_callback, clock_type);
non_cached_buffer = std::move(buffer);
data_buffer = non_cached_buffer.get();
}
2019-10-11 15:37:16 +00:00
}
size_t MergeTreeReaderCompact::readRows(size_t from_mark, bool continue_reading, size_t max_rows_to_read, Block & res)
{
UNUSED(from_mark);
UNUSED(continue_reading);
UNUSED(max_rows_to_read);
UNUSED(res);
2019-11-25 11:06:59 +00:00
/// FIXME compute correct granularity
2019-11-27 11:35:27 +00:00
std::cerr << "(MergeTreeReaderCompact::readRows) max_rows_to_read: " << max_rows_to_read << "\n";
2019-10-16 18:27:53 +00:00
size_t read_rows = 0;
2019-11-27 11:35:27 +00:00
while (read_rows < max_rows_to_read)
2019-10-16 18:27:53 +00:00
{
2019-11-27 11:35:27 +00:00
size_t rows_to_read = data_part->index_granularity.getMarkRows(from_mark);
2019-10-16 18:27:53 +00:00
2019-11-27 11:35:27 +00:00
std::cerr << "(MergeTreeReaderCompact::readRows) rows_to_read: " << rows_to_read << "\n";
2019-10-16 18:27:53 +00:00
2019-11-27 11:35:27 +00:00
for (const auto & it : columns)
2019-10-16 18:27:53 +00:00
{
2019-11-27 11:35:27 +00:00
bool append = res.has(it.name);
if (!append)
res.insert(ColumnWithTypeAndName(it.type->createColumn(), it.type, it.name));
/// To keep offsets shared. TODO Very dangerous. Get rid of this.
MutableColumnPtr column = res.getByName(it.name).column->assumeMutable();
try
{
// size_t column_size_before_reading = column->size();
size_t column_position = data_part->getColumnPosition(it.name);
readData(it.name, *it.type, *column, from_mark, column_position, rows_to_read);
/// For elements of Nested, column_size_before_reading may be greater than column size
/// if offsets are not empty and were already read, but elements are empty.
/// FIXME
// if (column->size())
// read_rows_in_mark = std::max(read_rows, column->size() - column_size_before_reading);
}
catch (Exception & e)
{
/// Better diagnostics.
e.addMessage("(while reading column " + it.name + ")");
throw;
}
2019-10-16 18:27:53 +00:00
if (column->size())
2019-11-27 11:35:27 +00:00
res.getByName(it.name).column = std::move(column);
else
res.erase(it.name);
2019-10-16 18:27:53 +00:00
}
2019-11-27 11:35:27 +00:00
++from_mark;
read_rows += rows_to_read;
2019-10-16 18:27:53 +00:00
}
2019-11-27 11:35:27 +00:00
std::cerr << "(MergeTreeReaderCompact::readRows) read_rows: " << read_rows << "\n";
2019-10-16 18:27:53 +00:00
return read_rows;
2019-10-11 15:37:16 +00:00
}
2019-10-16 18:27:53 +00:00
void MergeTreeReaderCompact::readData(
const String & name, const IDataType & type, IColumn & column,
size_t from_mark, size_t column_position, size_t rows_to_read)
{
2019-10-31 14:44:17 +00:00
std::cerr << "(MergeTreeReaderCompact::readData) from_mark: " << from_mark << "\n";
std::cerr << "(MergeTreeReaderCompact::readData) column_position: " << column_position << "\n";
std::cerr << "(MergeTreeReaderCompact::readData) rows_to_read: " << rows_to_read << "\n";
std::cerr << "(MergeTreeReaderCompact::readData) start reading column: " << name << "\n";
2019-10-16 18:27:53 +00:00
seekToMark(from_mark, column_position);
IDataType::DeserializeBinaryBulkSettings deserialize_settings;
deserialize_settings.getter = [&](IDataType::SubstreamPath) -> ReadBuffer * { return data_buffer; };
deserialize_settings.avg_value_size_hint = avg_value_size_hints[name];
deserialize_settings.position_independent_encoding = false;
IDataType::DeserializeBinaryBulkStatePtr state;
type.deserializeBinaryBulkStatePrefix(deserialize_settings, state);
type.deserializeBinaryBulkWithMultipleStreams(column, rows_to_read, deserialize_settings, state);
2019-11-25 11:06:59 +00:00
std::cerr << "(MergeTreeReaderCompact::readData) end reading column rows: " << column.size() << "\n";
2019-10-31 14:44:17 +00:00
std::cerr << "(MergeTreeReaderCompact::readData) end reading column: " << name << "\n";
// if (column.size() != rows_to_read)
// throw Exception("Cannot read all data in NativeBlockInputStream. Rows read: " + toString(column.size()) + ". Rows expected: "+ toString(rows_to_read) + ".",
// ErrorCodes::CANNOT_READ_ALL_DATA);
2019-10-16 18:27:53 +00:00
}
2019-11-20 13:33:41 +00:00
void MergeTreeReaderCompact::initMarksLoader()
2019-10-11 15:37:16 +00:00
{
2019-11-21 16:10:22 +00:00
if (marks_loader.initialized())
return;
2019-11-20 13:33:41 +00:00
size_t columns_num = data_part->columns.size();
2019-10-11 15:37:16 +00:00
2019-11-25 20:19:43 +00:00
auto load = [this, columns_num](const String & mrk_path) -> MarkCache::MappedPtr
2019-10-11 15:37:16 +00:00
{
size_t file_size = Poco::File(mrk_path).getSize();
2019-11-25 11:06:59 +00:00
size_t marks_count = data_part->getMarksCount();
size_t mark_size_in_bytes = data_part->index_granularity_info.mark_size_in_bytes;
2019-10-31 14:44:17 +00:00
2019-11-25 11:06:59 +00:00
std::cerr << "(initMarksLoader) marks_count: " << marks_count << "\n";
std::cerr << "() mark_size_in_bytes: " << mark_size_in_bytes << "\n";
size_t expected_file_size = mark_size_in_bytes * marks_count;
2019-10-11 15:37:16 +00:00
if (expected_file_size != file_size)
throw Exception(
"Bad size of marks file '" + mrk_path + "': " + std::to_string(file_size) + ", must be: " + std::to_string(expected_file_size),
ErrorCodes::CORRUPTED_DATA);
/// Memory for marks must not be accounted as memory usage for query, because they are stored in shared cache.
auto temporarily_disable_memory_tracker = getCurrentMemoryTrackerActionLock();
2019-10-31 14:44:17 +00:00
auto res = std::make_shared<MarksInCompressedFile>(marks_count * columns_num);
2019-11-27 11:35:27 +00:00
// std::cerr << "(MergeTreeReaderCompact::loadMarks) marks_count: " << marks_count << "\n";
2019-10-11 15:37:16 +00:00
ReadBufferFromFile buffer(mrk_path, file_size);
size_t i = 0;
while (!buffer.eof())
{
2019-10-31 14:44:17 +00:00
buffer.seek(sizeof(size_t), SEEK_CUR);
buffer.readStrict(reinterpret_cast<char *>(res->data() + i * columns_num), sizeof(MarkInCompressedFile) * columns_num);
2019-11-27 11:35:27 +00:00
// std::cerr << "(MergeTreeReaderCompact::loadMarks) i: " << i << "\n";
// std::cerr << "(MergeTreeReaderCompact::loadMarks) buffer pos in file: " << buffer.getPositionInFile() << "\n";
2019-10-11 15:37:16 +00:00
++i;
}
2019-11-27 11:35:27 +00:00
// std::cerr << "(MergeTreeReaderCompact::loadMarks) file_size: " << file_size << "\n";
// std::cerr << "(MergeTreeReaderCompact::loadMarks) correct file size: " << i * mark_size_in_bytes << "\n";
2019-10-31 14:44:17 +00:00
2019-11-25 11:06:59 +00:00
if (i * mark_size_in_bytes != file_size)
2019-10-11 15:37:16 +00:00
throw Exception("Cannot read all marks from file " + mrk_path, ErrorCodes::CANNOT_READ_ALL_DATA);
res->protect();
return res;
};
2019-11-25 20:19:43 +00:00
auto mrk_path = data_part->index_granularity_info.getMarksFilePath(path + NAME_OF_FILE_WITH_DATA);
marks_loader = MergeTreeMarksLoader{mark_cache, std::move(mrk_path), load, settings.save_marks_in_cache, columns_num};
2019-10-11 15:37:16 +00:00
}
2019-11-20 13:33:41 +00:00
void MergeTreeReaderCompact::seekToMark(size_t row_index, size_t column_index)
2019-10-16 18:27:53 +00:00
{
2019-11-20 13:33:41 +00:00
MarkInCompressedFile mark = marks_loader.getMark(row_index, column_index);
2019-10-16 18:27:53 +00:00
2019-10-31 14:44:17 +00:00
std::cerr << "(MergeTreeReaderCompact::seekToMark) mark: (" << mark.offset_in_compressed_file << ", " << mark.offset_in_decompressed_block << "\n";
2019-10-16 18:27:53 +00:00
try
{
if (cached_buffer)
cached_buffer->seek(mark.offset_in_compressed_file, mark.offset_in_decompressed_block);
if (non_cached_buffer)
non_cached_buffer->seek(mark.offset_in_compressed_file, mark.offset_in_decompressed_block);
}
catch (Exception & e)
{
/// Better diagnostics.
if (e.code() == ErrorCodes::ARGUMENT_OUT_OF_BOUND)
2019-11-20 13:33:41 +00:00
e.addMessage("(while seeking to mark (" + toString(row_index) + ", " + toString(column_index) + ")");
2019-10-16 18:27:53 +00:00
throw;
}
}
void MergeTreeReaderCompact::seekToStart()
{
if (cached_buffer)
cached_buffer->seek(0, 0);
if (non_cached_buffer)
non_cached_buffer->seek(0, 0);
}
2019-10-11 15:37:16 +00:00
}