mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-23 16:12:01 +00:00
Merge
This commit is contained in:
commit
ba3f35f83c
@ -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);
|
||||
|
||||
/** Перешардирует заданную партицию.
|
||||
*/
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,28 +1039,55 @@ 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();
|
||||
|
||||
zookeeper->multi(ops);
|
||||
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.");
|
||||
}
|
||||
}
|
||||
|
||||
/** Удаление старых кусков из ZK и с диска делается отложенно - см. ReplicatedMergeTreeCleanupThread, clearOldParts.
|
||||
*/
|
||||
if (!do_fetch)
|
||||
{
|
||||
merger.renameMergedTemporaryPart(parts, part, entry.new_part_name, &transaction);
|
||||
zookeeper->multi(ops);
|
||||
|
||||
/** При ZCONNECTIONLOSS или ZOPERATIONTIMEOUT можем зря откатить локальные изменения кусков.
|
||||
* Это не проблема, потому что в таком случае слияние останется в очереди, и мы попробуем снова.
|
||||
*/
|
||||
transaction.commit();
|
||||
merge_selecting_event.set();
|
||||
/** Удаление старых кусков из ZK и с диска делается отложенно - см. ReplicatedMergeTreeCleanupThread, clearOldParts.
|
||||
*/
|
||||
|
||||
ProfileEvents::increment(ProfileEvents::ReplicatedPartMerges);
|
||||
/** При ZCONNECTIONLOSS или ZOPERATIONTIMEOUT можем зря откатить локальные изменения кусков.
|
||||
* Это не проблема, потому что в таком случае слияние останется в очереди, и мы попробуем снова.
|
||||
*/
|
||||
transaction.commit();
|
||||
merge_selecting_event.set();
|
||||
|
||||
ProfileEvents::increment(ProfileEvents::ReplicatedPartMerges);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user