This commit is contained in:
Alexey Milovidov 2016-03-31 15:21:57 +03:00
commit ba3f35f83c
10 changed files with 204 additions and 97 deletions

View File

@ -48,11 +48,19 @@ public:
/** Сливает куски.
* Если reservation != nullptr, то и дело уменьшает размер зарезервированного места
* приблизительно пропорционально количеству уже выписанных данных.
*
* Создаёт и возвращает временный кусок.
* Чтобы закончить мердж, вызовите функцию renameTemporaryMergedPart.
*/
MergeTreeData::DataPartPtr mergeParts(
MergeTreeData::MutableDataPartPtr mergePartsToTemporaryPart(
MergeTreeData::DataPartsVector & parts, const String & merged_name, MergeListEntry & merge_entry,
size_t aio_threshold, MergeTreeData::Transaction * out_transaction = nullptr,
DiskSpaceMonitor::Reservation * disk_reservation = nullptr);
size_t aio_threshold, DiskSpaceMonitor::Reservation * disk_reservation = nullptr);
MergeTreeData::DataPartPtr renameMergedTemporaryPart(
MergeTreeData::DataPartsVector & parts,
MergeTreeData::MutableDataPartPtr & new_data_part,
const String & merged_name,
MergeTreeData::Transaction * out_transaction = nullptr);
/** Перешардирует заданную партицию.
*/

View File

@ -32,7 +32,8 @@ public:
String path,
const Settings & settings,
const DataTypes & primary_key_data_types, /// Проверять первичный ключ. Если не надо - передайте пустой массив.
MergeTreeData::DataPart::Checksums * out_checksums = nullptr);
MergeTreeData::DataPart::Checksums * out_checksums = nullptr,
volatile bool * is_cancelled = nullptr);
};
}

View File

@ -313,6 +313,7 @@ bool MergeTreeDataMerger::selectPartsToMerge(MergeTreeData::DataPartsVector & pa
return found;
}
MergeTreeData::DataPartsVector MergeTreeDataMerger::selectAllPartsFromPartition(DayNum_t partition)
{
MergeTreeData::DataPartsVector parts_from_partition;
@ -332,11 +333,11 @@ MergeTreeData::DataPartsVector MergeTreeDataMerger::selectAllPartsFromPartition(
return parts_from_partition;
}
/// parts должны быть отсортированы.
MergeTreeData::DataPartPtr MergeTreeDataMerger::mergeParts(
MergeTreeData::MutableDataPartPtr MergeTreeDataMerger::mergePartsToTemporaryPart(
MergeTreeData::DataPartsVector & parts, const String & merged_name, MergeList::Entry & merge_entry,
size_t aio_threshold, MergeTreeData::Transaction * out_transaction,
DiskSpaceMonitor::Reservation * disk_reservation)
size_t aio_threshold, DiskSpaceMonitor::Reservation * disk_reservation)
{
merge_entry->num_parts = parts.size();
@ -486,6 +487,16 @@ MergeTreeData::DataPartPtr MergeTreeDataMerger::mergeParts(
new_data_part->size_in_bytes = MergeTreeData::DataPart::calcTotalSize(new_part_tmp_path);
new_data_part->is_sharded = false;
return new_data_part;
}
MergeTreeData::DataPartPtr MergeTreeDataMerger::renameMergedTemporaryPart(
MergeTreeData::DataPartsVector & parts,
MergeTreeData::MutableDataPartPtr & new_data_part,
const String & merged_name,
MergeTreeData::Transaction * out_transaction)
{
/// Переименовываем новый кусок, добавляем в набор и убираем исходные куски.
auto replaced_parts = data.renameTempPartAndReplace(new_data_part, nullptr, out_transaction);
@ -522,10 +533,10 @@ MergeTreeData::DataPartPtr MergeTreeDataMerger::mergeParts(
}
LOG_TRACE(log, "Merged " << parts.size() << " parts: from " << parts.front()->name << " to " << parts.back()->name);
return new_data_part;
}
MergeTreeData::PerShardDataParts MergeTreeDataMerger::reshardPartition(
const ReshardingJob & job, DiskSpaceMonitor::Reservation * disk_reservation)
{

View File

@ -41,9 +41,9 @@ void MergeTreeDataPartChecksum::checkEqual(const MergeTreeDataPartChecksum & rhs
if (!rhs.is_compressed)
throw Exception("No uncompressed checksum for file " + name, ErrorCodes::CHECKSUM_DOESNT_MATCH);
if (rhs.uncompressed_size != uncompressed_size)
throw Exception("Unexpected size of file " + name + " in data part", ErrorCodes::BAD_SIZE_OF_FILE_IN_DATA_PART);
throw Exception("Unexpected uncompressed size of file " + name + " in data part", ErrorCodes::BAD_SIZE_OF_FILE_IN_DATA_PART);
if (rhs.uncompressed_hash != uncompressed_hash)
throw Exception("Checksum mismatch for file " + name + " in data part", ErrorCodes::CHECKSUM_DOESNT_MATCH);
throw Exception("Checksum mismatch for uncompressed file " + name + " in data part", ErrorCodes::CHECKSUM_DOESNT_MATCH);
return;
}
if (rhs.file_size != file_size)

View File

@ -27,11 +27,15 @@ namespace ErrorCodes
}
namespace
{
struct Stream
{
static const size_t UNKNOWN = std::numeric_limits<size_t>::max();
DataTypePtr type;
bool data_type_is_string = false;
size_t data_type_fixed_length = 0;
String path;
String name;
@ -43,9 +47,36 @@ struct Stream
ReadBufferFromFile mrk_file_buf;
HashingReadBuffer mrk_hashing_buf;
Stream(const String & path_, const String & name_, DataTypePtr type_) : type(type_), path(path_), name(name_),
Stream(const String & path_, const String & name_, DataTypePtr type) : path(path_), name(name_),
file_buf(path + name + ".bin"), compressed_hashing_buf(file_buf), uncompressing_buf(compressed_hashing_buf),
uncompressed_hashing_buf(uncompressing_buf), mrk_file_buf(path + name + ".mrk"), mrk_hashing_buf(mrk_file_buf) {}
uncompressed_hashing_buf(uncompressing_buf), mrk_file_buf(path + name + ".mrk"), mrk_hashing_buf(mrk_file_buf)
{
data_type_is_string = typeid_cast<const DataTypeString *>(type.get());
if (!data_type_is_string)
{
if (typeid_cast<const DataTypeUInt8 *>(type.get())
|| typeid_cast<const DataTypeInt8 *>(type.get()))
data_type_fixed_length = sizeof(UInt8);
else if (typeid_cast<const DataTypeUInt16 *>(type.get())
|| typeid_cast<const DataTypeInt16 *>(type.get())
|| typeid_cast<const DataTypeDate *>(type.get()))
data_type_fixed_length = sizeof(UInt16);
else if (typeid_cast<const DataTypeUInt32 *>(type.get())
|| typeid_cast<const DataTypeInt32 *>(type.get())
|| typeid_cast<const DataTypeFloat32 *>(type.get())
|| typeid_cast<const DataTypeDateTime *>(type.get()))
data_type_fixed_length = sizeof(UInt32);
else if (typeid_cast<const DataTypeUInt64 *>(type.get())
|| typeid_cast<const DataTypeInt64 *>(type.get())
|| typeid_cast<const DataTypeFloat64 *>(type.get()))
data_type_fixed_length = sizeof(UInt64);
else if (auto string = typeid_cast<const DataTypeFixedString *>(type.get()))
data_type_fixed_length = string->getN();
else
throw Exception("Unexpected data type: " + type->getName() + " of column " + name, ErrorCodes::UNKNOWN_TYPE);
}
}
bool marksEOF()
{
@ -60,7 +91,7 @@ struct Stream
size_t read(size_t rows)
{
if (typeid_cast<const DataTypeString *>(type.get()))
if (data_type_is_string)
{
for (size_t i = 0; i < rows; ++i)
{
@ -79,33 +110,11 @@ struct Stream
}
else
{
size_t length;
if( typeid_cast<const DataTypeUInt8 *>(type.get()) ||
typeid_cast<const DataTypeInt8 *>(type.get()))
length = sizeof(UInt8);
else if(typeid_cast<const DataTypeUInt16 *>(type.get()) ||
typeid_cast<const DataTypeInt16 *>(type.get()) ||
typeid_cast<const DataTypeDate *>(type.get()))
length = sizeof(UInt16);
else if(typeid_cast<const DataTypeUInt32 *>(type.get()) ||
typeid_cast<const DataTypeInt32 *>(type.get()) ||
typeid_cast<const DataTypeFloat32 *>(type.get()) ||
typeid_cast<const DataTypeDateTime *>(type.get()))
length = sizeof(UInt32);
else if(typeid_cast<const DataTypeUInt64 *>(type.get()) ||
typeid_cast<const DataTypeInt64 *>(type.get()) ||
typeid_cast<const DataTypeFloat64 *>(type.get()))
length = sizeof(UInt64);
else if (auto string = typeid_cast<const DataTypeFixedString *>(type.get()))
length = string->getN();
else
throw Exception("Unexpected data type: " + type->getName() + " of column " + name, ErrorCodes::UNKNOWN_TYPE);
size_t size = uncompressed_hashing_buf.tryIgnore(length * rows);
if (size % length)
throw Exception("Read " + toString(size) + " bytes, which is not divisible by " + toString(length),
size_t size = uncompressed_hashing_buf.tryIgnore(data_type_fixed_length * rows);
if (size % data_type_fixed_length)
throw Exception("Read " + toString(size) + " bytes, which is not divisible by " + toString(data_type_fixed_length),
ErrorCodes::CORRUPTED_DATA);
return size / length;
return size / data_type_fixed_length;
}
}
@ -175,8 +184,13 @@ struct Stream
};
/// Возвращает количество строк. Добавляет в checksums чексуммы всех файлов столбца.
static size_t checkColumn(const String & path, const String & name, DataTypePtr type, const MergeTreePartChecker::Settings & settings,
MergeTreeData::DataPart::Checksums & checksums)
static size_t checkColumn(
const String & path,
const String & name,
DataTypePtr type,
const MergeTreePartChecker::Settings & settings,
MergeTreeData::DataPart::Checksums & checksums,
volatile bool * is_cancelled)
{
size_t rows = 0;
@ -191,6 +205,9 @@ static size_t checkColumn(const String & path, const String & name, DataTypePtr
ColumnUInt64::Container_t sizes;
while (true)
{
if (is_cancelled && *is_cancelled)
return 0;
if (sizes_stream.marksEOF())
break;
@ -233,6 +250,9 @@ static size_t checkColumn(const String & path, const String & name, DataTypePtr
size_t rows = 0;
while (true)
{
if (is_cancelled && *is_cancelled)
return 0;
if (data_stream.marksEOF())
break;
@ -260,11 +280,15 @@ static size_t checkColumn(const String & path, const String & name, DataTypePtr
}
}
}
void MergeTreePartChecker::checkDataPart(
String path,
const Settings & settings,
const DataTypes & primary_key_data_types,
MergeTreeData::DataPart::Checksums * out_checksums)
MergeTreeData::DataPart::Checksums * out_checksums,
volatile bool * is_cancelled)
{
CurrentMetrics::Increment metric_increment{CurrentMetrics::ReplicatedChecks};
@ -307,6 +331,9 @@ void MergeTreePartChecker::checkDataPart(
while (!hashing_buf.eof())
{
if (is_cancelled && *is_cancelled)
return;
++marks_in_primary_key;
for (size_t j = 0; j < key_size; ++j)
primary_key_data_types[j].get()->deserializeBinary(*tmp_columns[j].get(), hashing_buf);
@ -322,6 +349,9 @@ void MergeTreePartChecker::checkDataPart(
checksums_data.files["primary.idx"] = MergeTreeData::DataPart::Checksums::Checksum(primary_idx_size, hashing_buf.getHash());
}
if (is_cancelled && *is_cancelled)
return;
String any_column_name;
size_t rows = Stream::UNKNOWN;
std::exception_ptr first_exception;
@ -344,7 +374,11 @@ void MergeTreePartChecker::checkDataPart(
continue;
}
size_t cur_rows = checkColumn(path, column.name, column.type, settings, checksums_data);
size_t cur_rows = checkColumn(path, column.name, column.type, settings, checksums_data, is_cancelled);
if (is_cancelled && *is_cancelled)
return;
if (cur_rows != Stream::UNKNOWN)
{
if (rows == Stream::UNKNOWN)

View File

@ -257,7 +257,11 @@ bool StorageMergeTree::merge(size_t aio_threshold, bool aggressive, BackgroundPr
}
const auto & merge_entry = context.getMergeList().insert(database_name, table_name, merged_name);
merger.mergeParts(merging_tagger->parts, merged_name, *merge_entry, aio_threshold, nullptr, &*merging_tagger->reserved_space);
auto new_part = merger.mergePartsToTemporaryPart(
merging_tagger->parts, merged_name, *merge_entry, aio_threshold, &*merging_tagger->reserved_space);
merger.renameMergedTemporaryPart(merging_tagger->parts, new_part, merged_name, nullptr);
return true;
}

View File

@ -83,6 +83,8 @@ namespace ErrorCodes
extern const int RESHARDING_INVALID_QUERY;
extern const int RWLOCK_NO_SUCH_LOCK;
extern const int NO_SUCH_BARRIER;
extern const int CHECKSUM_DOESNT_MATCH;
extern const int BAD_SIZE_OF_FILE_IN_DATA_PART;
}
@ -817,7 +819,8 @@ void StorageReplicatedMergeTree::checkParts(bool skip_sanity_checks)
}
void StorageReplicatedMergeTree::checkPartAndAddToZooKeeper(const MergeTreeData::DataPartPtr & part, zkutil::Ops & ops, String part_name)
void StorageReplicatedMergeTree::checkPartAndAddToZooKeeper(
const MergeTreeData::DataPartPtr & part, zkutil::Ops & ops, String part_name)
{
auto zookeeper = getZooKeeper();
@ -1036,16 +1039,42 @@ bool StorageReplicatedMergeTree::executeLogEntry(const LogEntry & entry, Backgro
MergeTreeData::Transaction transaction;
size_t aio_threshold = context.getSettings().min_bytes_to_use_direct_io;
MergeTreeData::DataPartPtr part = merger.mergeParts(
parts, entry.new_part_name, *merge_entry, aio_threshold, &transaction, reserved_space);
auto part = merger.mergePartsToTemporaryPart(
parts, entry.new_part_name, *merge_entry, aio_threshold, reserved_space);
zkutil::Ops ops;
checkPartAndAddToZooKeeper(part, ops);
/** TODO: Переименование нового куска лучше делать здесь, а не пятью строчками выше,
* чтобы оно было как можно ближе к zookeeper->multi.
*/
try
{
/// Здесь проверяются чексуммы и заполняется ops. Реально кусок добавляется в ZK чуть ниже, при выполнении multi.
checkPartAndAddToZooKeeper(part, ops, entry.new_part_name);
}
catch (const Exception & e)
{
if (e.code() == ErrorCodes::CHECKSUM_DOESNT_MATCH
|| e.code() == ErrorCodes::BAD_SIZE_OF_FILE_IN_DATA_PART)
{
do_fetch = true;
part->remove();
LOG_ERROR(log, getCurrentExceptionMessage(false) << ". "
"Data after merge is not byte-identical to data on another replicas. "
"There could be several reasons: "
"1. Using newer version of compression library after server update. "
"2. Using another compression method. "
"3. Non-deterministic compression algorithm (highly unlikely). "
"4. Non-deterministic merge algorithm due to logical error in code. "
"5. Data corruption in memory due to bug in code. "
"6. Data corruption in memory due to hardware issue. "
"7. Manual modification of source data after server starup. "
"8. Manual modification of checksums stored in ZooKeeper. "
"We will download merged part from replica to force byte-identical result.");
}
}
if (!do_fetch)
{
merger.renameMergedTemporaryPart(parts, part, entry.new_part_name, &transaction);
zookeeper->multi(ops);
/** Удаление старых кусков из ZK и с диска делается отложенно - см. ReplicatedMergeTreeCleanupThread, clearOldParts.
@ -1060,6 +1089,7 @@ bool StorageReplicatedMergeTree::executeLogEntry(const LogEntry & entry, Backgro
ProfileEvents::increment(ProfileEvents::ReplicatedPartMerges);
}
}
}
else
{
throw Exception("Unexpected log entry type: " + toString(static_cast<int>(entry.type)));
@ -2101,8 +2131,15 @@ void StorageReplicatedMergeTree::checkPart(const String & part_name)
settings.setIndexGranularity(data.index_granularity);
settings.setRequireChecksums(true);
settings.setRequireColumnFiles(true);
MergeTreePartChecker::checkDataPart(
data.getFullPath() + part_name, settings, data.primary_key_data_types);
data.getFullPath() + part_name, settings, data.primary_key_data_types, nullptr, &shutdown_called);
if (shutdown_called)
{
LOG_INFO(log, "Checking part was cancelled.");
return;
}
LOG_INFO(log, "Checker: Part " << part_name << " looks good.");
}
@ -2131,6 +2168,11 @@ void StorageReplicatedMergeTree::checkPart(const String & part_name)
}
else
{
/// TODO Надо сделать так, чтобы кусок всё-таки проверился через некоторое время.
/// Иначе возможна ситуация, что кусок не добавился в ZK,
/// но остался в файловой системе и в множестве активных кусков.
/// И тогда в течение долгого времени (до перезапуска), данные на репликах будут разными.
LOG_TRACE(log, "Checker: Young part " << part_name
<< " with age " << (time(0) - part->modification_time)
<< " seconds hasn't been added to ZooKeeper yet. It's ok.");
@ -2179,6 +2221,9 @@ void StorageReplicatedMergeTree::partCheckThread()
checkPart(part_name);
if (shutdown_called)
break;
/// Удалим кусок из очереди проверок.
{
std::lock_guard<std::mutex> lock(parts_to_check_mutex);
@ -2587,7 +2632,11 @@ bool StorageReplicatedMergeTree::optimize(const Settings & settings)
return false;
const auto & merge_entry = context.getMergeList().insert(database_name, table_name, merged_name);
unreplicated_merger->mergeParts(parts, merged_name, *merge_entry, settings.min_bytes_to_use_direct_io);
auto new_part = unreplicated_merger->mergePartsToTemporaryPart(
parts, merged_name, *merge_entry, settings.min_bytes_to_use_direct_io);
unreplicated_merger->renameMergedTemporaryPart(parts, new_part, merged_name, nullptr);
return true;
}

View File

@ -1,35 +1,35 @@
1 1.00 B 1 1.00 B 1 1.00 B
2.7182818284590455 2.72 B 2 2.00 B 2 2.00 B
7.38905609893065 7.39 B 7 7.00 B 7 7.00 B
20.085536923187668 20.09 B 20 20.00 B 20 20.00 B
54.598150033144236 54.60 B 54 54.00 B 54 54.00 B
148.4131591025766 148.41 B 148 148.00 B 148 148.00 B
403.4287934927351 403.43 B 403 403.00 B 403 403.00 B
1096.6331584284585 1.07 KiB 1096 1.07 KiB 1096 1.07 KiB
2980.9579870417283 2.91 KiB 2980 2.91 KiB 2980 2.91 KiB
8103.083927575384 7.91 KiB 8103 7.91 KiB 8103 7.91 KiB
22026.465794806718 21.51 KiB 22026 21.51 KiB 22026 21.51 KiB
59874.14171519782 58.47 KiB 59874 58.47 KiB 59874 58.47 KiB
162754.79141900392 158.94 KiB 162754 158.94 KiB 162754 158.94 KiB
442413.3920089205 432.04 KiB 442413 432.04 KiB 442413 432.04 KiB
1202604.2841647768 1.15 MiB 1202604 1.15 MiB 1202604 1.15 MiB
3269017.3724721107 3.12 MiB 3269017 3.12 MiB 3269017 3.12 MiB
8886110.520507872 8.47 MiB 8886110 8.47 MiB 8886110 8.47 MiB
24154952.753575303 23.04 MiB 24154952 23.04 MiB 24154952 23.04 MiB
65659969.13733051 62.62 MiB 65659969 62.62 MiB 65659969 62.62 MiB
178482300.96318728 170.21 MiB 178482300 170.21 MiB 178482300 170.21 MiB
485165195.4097903 462.69 MiB 485165195 462.69 MiB 485165195 462.69 MiB
1318815734.4832149 1.23 GiB 1318815734 1.23 GiB 1318815734 1.23 GiB
3584912846.1315913 3.34 GiB 3584912846 3.34 GiB -710054450 -677.16 MiB
2.718282 2.72 B 2 2.00 B 2 2.00 B
7.389056 7.39 B 7 7.00 B 7 7.00 B
20.085537 20.09 B 20 20.00 B 20 20.00 B
54.59815 54.60 B 54 54.00 B 54 54.00 B
148.413159 148.41 B 148 148.00 B 148 148.00 B
403.428793 403.43 B 403 403.00 B 403 403.00 B
1096.633158 1.07 KiB 1096 1.07 KiB 1096 1.07 KiB
2980.957987 2.91 KiB 2980 2.91 KiB 2980 2.91 KiB
8103.083928 7.91 KiB 8103 7.91 KiB 8103 7.91 KiB
22026.465795 21.51 KiB 22026 21.51 KiB 22026 21.51 KiB
59874.141715 58.47 KiB 59874 58.47 KiB 59874 58.47 KiB
162754.791419 158.94 KiB 162754 158.94 KiB 162754 158.94 KiB
442413.392009 432.04 KiB 442413 432.04 KiB 442413 432.04 KiB
1202604.284165 1.15 MiB 1202604 1.15 MiB 1202604 1.15 MiB
3269017.372472 3.12 MiB 3269017 3.12 MiB 3269017 3.12 MiB
8886110.520508 8.47 MiB 8886110 8.47 MiB 8886110 8.47 MiB
24154952.753575 23.04 MiB 24154952 23.04 MiB 24154952 23.04 MiB
65659969.137331 62.62 MiB 65659969 62.62 MiB 65659969 62.62 MiB
178482300.963187 170.21 MiB 178482300 170.21 MiB 178482300 170.21 MiB
485165195.40979 462.69 MiB 485165195 462.69 MiB 485165195 462.69 MiB
1318815734.483214 1.23 GiB 1318815734 1.23 GiB 1318815734 1.23 GiB
3584912846.131592 3.34 GiB 3584912846 3.34 GiB -710054450 -677.16 MiB
9744803446.248903 9.08 GiB 9744803446 9.08 GiB 1154868854 1.08 GiB
26489122129.84347 24.67 GiB 26489122129 24.67 GiB 719318353 686.00 MiB
72004899337.38588 67.06 GiB 72004899337 67.06 GiB -1009544695 -962.78 MiB
195729609428.83875 182.29 GiB 195729609428 182.29 GiB -1838886188 -1.71 GiB
195729609428.83878 182.29 GiB 195729609428 182.29 GiB -1838886188 -1.71 GiB
532048240601.79865 495.51 GiB 532048240601 495.51 GiB -527704103 -503.26 MiB
1446257064291.475 1.32 TiB 1446257064291 1.32 TiB -1146914461 -1.07 GiB
3931334297144.042 3.58 TiB 3931334297144 3.58 TiB 1439221304 1.34 GiB
10686474581524.46 9.72 TiB 10686474581524 9.72 TiB 595949076 568.34 MiB
29048849665247.42 26.42 TiB 29048849665247 26.42 TiB 1985842399 1.85 GiB
10686474581524.463 9.72 TiB 10686474581524 9.72 TiB 595949076 568.34 MiB
29048849665247.426 26.42 TiB 29048849665247 26.42 TiB 1985842399 1.85 GiB
78962960182680.69 71.82 TiB 78962960182680 71.82 TiB -13554280 -12.93 MiB
214643579785916.06 195.22 TiB 214643579785916 195.22 TiB -1705798980 -1.59 GiB
583461742527454.9 530.66 TiB 583461742527454 530.66 TiB -974699554 -929.55 MiB
@ -40,7 +40,7 @@
86593400423993740 76.91 PiB 86593400423993744 76.91 PiB 673862032 642.64 MiB
235385266837020000 209.06 PiB 235385266837020000 209.06 PiB 791567712 754.90 MiB
639843493530054900 568.30 PiB 639843493530054912 568.30 PiB 1874080000 1.75 GiB
1739274941520501200 1.51 EiB 1739274941520501248 1.51 EiB 538008064 513.08 MiB
1739274941520501000 1.51 EiB 1739274941520500992 1.51 EiB 538007808 513.08 MiB
4727839468229346000 4.10 EiB 4727839468229346304 4.10 EiB 2061616128 1.92 GiB
12851600114359308000 11.15 EiB 12851600114359308288 11.15 EiB -1681813504 -1.57 GiB
34934271057485095000 30.30 EiB 0 0.00 B 0 0.00 B
@ -49,9 +49,9 @@
701673591209763100000 608.60 EiB 0 0.00 B 0 0.00 B
1.9073465724950998e21 1.62 ZiB 0 0.00 B 0 0.00 B
5.184705528587072e21 4.39 ZiB 0 0.00 B 0 0.00 B
1.4093490824269386e22 11.94 ZiB 0 0.00 B 0 0.00 B
1.4093490824269389e22 11.94 ZiB 0 0.00 B 0 0.00 B
3.831008000716577e22 32.45 ZiB 0 0.00 B 0 0.00 B
1.0413759433029087e23 88.21 ZiB 0 0.00 B 0 0.00 B
1.0413759433029089e23 88.21 ZiB 0 0.00 B 0 0.00 B
2.830753303274694e23 239.77 ZiB 0 0.00 B 0 0.00 B
7.694785265142018e23 651.77 ZiB 0 0.00 B 0 0.00 B
2.091659496012996e24 1.73 YiB 0 0.00 B 0 0.00 B
@ -60,10 +60,10 @@
4.2012104037905144e25 34.75 YiB 0 0.00 B 0 0.00 B
1.1420073898156842e26 94.46 YiB 0 0.00 B 0 0.00 B
3.10429793570192e26 256.78 YiB 0 0.00 B 0 0.00 B
8.438356668741455e26 698.00 YiB 0 0.00 B 0 0.00 B
8.438356668741454e26 698.00 YiB 0 0.00 B 0 0.00 B
2.29378315946961e27 1897.37 YiB 0 0.00 B 0 0.00 B
6.235149080811617e27 5157.59 YiB 0 0.00 B 0 0.00 B
1.6948892444103336e28 14019.80 YiB 0 0.00 B 0 0.00 B
1.6948892444103338e28 14019.80 YiB 0 0.00 B 0 0.00 B
4.607186634331292e28 38109.75 YiB 0 0.00 B 0 0.00 B
1.2523631708422137e29 103593.05 YiB 0 0.00 B 0 0.00 B
3.404276049931741e29 281595.11 YiB 0 0.00 B 0 0.00 B

View File

@ -1 +1 @@
SELECT exp(number) AS x, formatReadableSize(x), toUInt64(x) AS y, formatReadableSize(y), toInt32(y) AS z, formatReadableSize(z) FROM system.numbers LIMIT 70;
SELECT round(exp(number), 6) AS x, formatReadableSize(x), toUInt64(x) AS y, formatReadableSize(y), toInt32(y) AS z, formatReadableSize(z) FROM system.numbers LIMIT 70;

View File

@ -1,9 +1,9 @@
SELECT reverse('Hello');
SELECT reverse(materialize('Hello'));
SELECT reverse(toString(exp10(number))) FROM system.numbers LIMIT 10;
SELECT reverse(toString(round(exp10(number)))) FROM system.numbers LIMIT 10;
SELECT reverse(['Hello', 'World']);
SELECT reverse(materialize(['Hello', 'World']));
SELECT reverse(range(number)) FROM system.numbers LIMIT 10;
SELECT reverse(arrayMap(x -> toString(exp10(x)), range(number))) FROM system.numbers LIMIT 10;
SELECT reverse(toFixedString(toString(exp10(number)), 10)) FROM system.numbers LIMIT 10;
SELECT reverse(arrayMap(x -> toString(round(exp10(x))), range(number))) FROM system.numbers LIMIT 10;
SELECT reverse(toFixedString(toString(round(exp10(number))), 10)) FROM system.numbers LIMIT 10;