diff options
| author | ivanmorozov333 <[email protected]> | 2024-12-26 15:10:32 +0300 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-12-26 15:10:32 +0300 |
| commit | 2f6245280ebff5279b4ef653f44289857773e562 (patch) | |
| tree | ed475af18de6d468f446bd532d03ff0b19b2b089 | |
| parent | 24d1f57baa0f092f1c6a5c8bea907380d83962d2 (diff) | |
bloom ngramms speed up (#12982)
28 files changed, 345 insertions, 154 deletions
diff --git a/ydb/core/formats/arrow/hash/calcer.cpp b/ydb/core/formats/arrow/hash/calcer.cpp index d5fa4a8dd6a..8667f5b1110 100644 --- a/ydb/core/formats/arrow/hash/calcer.cpp +++ b/ydb/core/formats/arrow/hash/calcer.cpp @@ -9,7 +9,9 @@ namespace NKikimr::NArrow::NHash { -void TXX64::AppendField(const std::shared_ptr<arrow::Scalar>& scalar, NXX64::TStreamStringHashCalcer& hashCalcer) { +namespace { +template <class TStreamCalcer> +void AppendFieldImpl(const std::shared_ptr<arrow::Scalar>& scalar, TStreamCalcer& hashCalcer) { AFL_VERIFY(scalar); NArrow::SwitchType(scalar->type->id(), [&](const auto& type) { using TWrap = std::decay_t<decltype(type)>; @@ -28,7 +30,8 @@ void TXX64::AppendField(const std::shared_ptr<arrow::Scalar>& scalar, NXX64::TSt }); } -void TXX64::AppendField(const std::shared_ptr<arrow::Array>& array, const int row, NArrow::NHash::NXX64::TStreamStringHashCalcer& hashCalcer) { +template <class TStreamCalcer> +void AppendFieldImpl(const std::shared_ptr<arrow::Array>& array, const int row, TStreamCalcer& hashCalcer) { NArrow::SwitchType(array->type_id(), [&](const auto& type) { using TWrap = std::decay_t<decltype(type)>; using T = typename TWrap::T; @@ -49,6 +52,24 @@ void TXX64::AppendField(const std::shared_ptr<arrow::Array>& array, const int ro }); } +} // namespace + +void TXX64::AppendField(const std::shared_ptr<arrow::Scalar>& scalar, NXX64::TStreamStringHashCalcer& hashCalcer) { + AppendFieldImpl(scalar, hashCalcer); +} + +void TXX64::AppendField(const std::shared_ptr<arrow::Scalar>& scalar, NXX64::TStreamStringHashCalcer_H3& hashCalcer) { + AppendFieldImpl(scalar, hashCalcer); +} + +void TXX64::AppendField(const std::shared_ptr<arrow::Array>& array, const int row, NArrow::NHash::NXX64::TStreamStringHashCalcer& hashCalcer) { + AppendFieldImpl(array, row, hashCalcer); +} + +void TXX64::AppendField(const std::shared_ptr<arrow::Array>& array, const int row, NArrow::NHash::NXX64::TStreamStringHashCalcer_H3& hashCalcer) { + AppendFieldImpl(array, row, hashCalcer); +} + std::optional<std::vector<ui64>> TXX64::Execute(const std::shared_ptr<arrow::RecordBatch>& batch) const { std::vector<std::shared_ptr<arrow::Array>> columns = GetColumns(batch); if (columns.empty()) { diff --git a/ydb/core/formats/arrow/hash/calcer.h b/ydb/core/formats/arrow/hash/calcer.h index 51dfe7858f8..490a0e05e36 100644 --- a/ydb/core/formats/arrow/hash/calcer.h +++ b/ydb/core/formats/arrow/hash/calcer.h @@ -67,6 +67,8 @@ public: static void AppendField(const std::shared_ptr<arrow::Array>& array, const int row, NXX64::TStreamStringHashCalcer& hashCalcer); static void AppendField(const std::shared_ptr<arrow::Scalar>& scalar, NXX64::TStreamStringHashCalcer& hashCalcer); + static void AppendField(const std::shared_ptr<arrow::Array>& array, const int row, NXX64::TStreamStringHashCalcer_H3& hashCalcer); + static void AppendField(const std::shared_ptr<arrow::Scalar>& scalar, NXX64::TStreamStringHashCalcer_H3& hashCalcer); static ui64 CalcHash(const std::shared_ptr<arrow::Scalar>& scalar); std::optional<std::vector<ui64>> Execute(const std::shared_ptr<arrow::RecordBatch>& batch) const; diff --git a/ydb/core/formats/arrow/permutations.cpp b/ydb/core/formats/arrow/permutations.cpp index 47e8037b860..2a7804c918e 100644 --- a/ydb/core/formats/arrow/permutations.cpp +++ b/ydb/core/formats/arrow/permutations.cpp @@ -11,7 +11,6 @@ #include <ydb/library/actors/core/log.h> #include <contrib/libs/apache/arrow/cpp/src/arrow/array/builder_primitive.h> -#include <contrib/libs/xxhash/xxhash.h> namespace NKikimr::NArrow { diff --git a/ydb/core/kqp/ut/olap/indexes_ut.cpp b/ydb/core/kqp/ut/olap/indexes_ut.cpp index 014b5c6abe3..56361a050ec 100644 --- a/ydb/core/kqp/ut/olap/indexes_ut.cpp +++ b/ydb/core/kqp/ut/olap/indexes_ut.cpp @@ -482,7 +482,7 @@ Y_UNIT_TEST_SUITE(KqpOlapIndexes) { } { ResetZeroLevel(csController); - ui32 requestsCount = 100; + ui32 requestsCount = 300; for (ui32 i = 0; i < requestsCount; ++i) { const ui32 idx = RandomNumber<ui32>(uids.size()); const auto query = [](const TString& res, const TString& uid, const ui32 level) { @@ -494,12 +494,12 @@ Y_UNIT_TEST_SUITE(KqpOlapIndexes) { }; ExecuteSQL(query(resourceIds[idx], uids[idx], levels[idx]), "[[1u;]]"); } - AFL_VERIFY(csController->GetIndexesSkippingOnSelect().Val() - SkipStart > 1)("approved", csController->GetIndexesApprovedOnSelect().Val() - ApproveStart)( + AFL_VERIFY(csController->GetIndexesSkippingOnSelect().Val() - SkipStart)("approved", csController->GetIndexesApprovedOnSelect().Val() - ApproveStart)( "skipped", csController->GetIndexesSkippingOnSelect().Val() - SkipStart); } { ResetZeroLevel(csController); - ui32 requestsCount = 100; + ui32 requestsCount = 300; for (ui32 i = 0; i < requestsCount; ++i) { const ui32 idx = RandomNumber<ui32>(uids.size()); const auto query = [](const TString& res, const TString& uid, const ui32 level) { @@ -511,13 +511,13 @@ Y_UNIT_TEST_SUITE(KqpOlapIndexes) { }; ExecuteSQL(query(resourceIds[idx], uids[idx], levels[idx]), "[[1u;]]"); } - AFL_VERIFY(csController->GetIndexesSkippingOnSelect().Val() - SkipStart > 1)( + AFL_VERIFY(csController->GetIndexesSkippingOnSelect().Val() - SkipStart)( "approved", csController->GetIndexesApprovedOnSelect().Val() - ApproveStart)( "skipped", csController->GetIndexesSkippingOnSelect().Val() - SkipStart); } { ResetZeroLevel(csController); - ui32 requestsCount = 100; + ui32 requestsCount = 300; for (ui32 i = 0; i < requestsCount; ++i) { const ui32 idx = RandomNumber<ui32>(uids.size()); const auto query = [](const TString& res, const TString& uid, const ui32 level) { @@ -529,7 +529,7 @@ Y_UNIT_TEST_SUITE(KqpOlapIndexes) { }; ExecuteSQL(query(resourceIds[idx], uids[idx], levels[idx]), "[[1u;]]"); } - AFL_VERIFY(csController->GetIndexesSkippingOnSelect().Val() - SkipStart > 1)( + AFL_VERIFY(csController->GetIndexesSkippingOnSelect().Val() - SkipStart)( "approved", csController->GetIndexesApprovedOnSelect().Val() - ApproveStart)( "skipped", csController->GetIndexesSkippingOnSelect().Val() - SkipStart); } diff --git a/ydb/core/tx/columnshard/engines/changes/compaction/merger.cpp b/ydb/core/tx/columnshard/engines/changes/compaction/merger.cpp index 5de37fa6154..9df83a6cb2d 100644 --- a/ydb/core/tx/columnshard/engines/changes/compaction/merger.cpp +++ b/ydb/core/tx/columnshard/engines/changes/compaction/merger.cpp @@ -147,7 +147,7 @@ std::vector<TWritePortionInfoWithBlobsResult> TMerger::Execute(const std::shared for (auto&& i : packs) { TGeneralSerializedSlice slicePrimary(std::move(i)); auto dataWithSecondary = resultFiltered->GetIndexInfo() - .AppendIndexes(slicePrimary.GetPortionChunksToHash(), SaverContext.GetStoragesManager()) + .AppendIndexes(slicePrimary.GetPortionChunksToHash(), SaverContext.GetStoragesManager(), slicePrimary.GetRecordsCount()) .DetachResult(); TGeneralSerializedSlice slice(dataWithSecondary.GetExternalData(), schemaDetails, Context.Counters.SplitterCounters); diff --git a/ydb/core/tx/columnshard/engines/portions/read_with_blobs.cpp b/ydb/core/tx/columnshard/engines/portions/read_with_blobs.cpp index a79207c07ac..6c040921608 100644 --- a/ydb/core/tx/columnshard/engines/portions/read_with_blobs.cpp +++ b/ydb/core/tx/columnshard/engines/portions/read_with_blobs.cpp @@ -124,7 +124,7 @@ std::optional<TWritePortionInfoWithBlobsResult> TReadPortionInfoWithBlobs::SyncP TIndexInfo::TSecondaryData secondaryData; secondaryData.MutableExternalData() = entityChunksNew; for (auto&& i : to->GetIndexInfo().GetIndexes()) { - to->GetIndexInfo().AppendIndex(entityChunksNew, i.first, storages, secondaryData).Validate(); + to->GetIndexInfo().AppendIndex(entityChunksNew, i.first, storages, source.PortionInfo.GetPortionInfo().GetRecordsCount(), secondaryData).Validate(); } const NSplitter::TEntityGroups groups = source.PortionInfo.GetPortionInfo().GetEntityGroupsByStorageId(targetTier, *storages, to->GetIndexInfo()); diff --git a/ydb/core/tx/columnshard/engines/reader/common_reader/iterator/fetching.h b/ydb/core/tx/columnshard/engines/reader/common_reader/iterator/fetching.h index 14ca43ec996..34b60a608f2 100644 --- a/ydb/core/tx/columnshard/engines/reader/common_reader/iterator/fetching.h +++ b/ydb/core/tx/columnshard/engines/reader/common_reader/iterator/fetching.h @@ -27,12 +27,12 @@ private: public: TFetchingStepSignals(NColumnShard::TCommonCountersOwner&& owner) : TBase(std::move(owner)) - , DurationCounter(TBase::GetDeriviative("duration_ms")) - , BytesCounter(TBase::GetDeriviative("bytes_ms")) { + , DurationCounter(TBase::GetDeriviative("Duration/Us")) + , BytesCounter(TBase::GetDeriviative("Bytes/Count")) { } void AddDuration(const TDuration d) const { - DurationCounter->Add(d.MilliSeconds()); + DurationCounter->Add(d.MicroSeconds()); } void AddBytes(const ui32 v) const { @@ -56,7 +56,7 @@ private: public: TFetchingStepsSignalsCollection() - : TBase("scan_steps") { + : TBase("ScanSteps") { } static TFetchingStepSignals GetSignals(const TString& name) { diff --git a/ydb/core/tx/columnshard/engines/scheme/index_info.cpp b/ydb/core/tx/columnshard/engines/scheme/index_info.cpp index 29d40e0032e..18fce9cf062 100644 --- a/ydb/core/tx/columnshard/engines/scheme/index_info.cpp +++ b/ydb/core/tx/columnshard/engines/scheme/index_info.cpp @@ -412,11 +412,11 @@ std::shared_ptr<arrow::Scalar> TIndexInfo::GetColumnExternalDefaultValueVerified } NKikimr::TConclusionStatus TIndexInfo::AppendIndex(const THashMap<ui32, std::vector<std::shared_ptr<IPortionDataChunk>>>& originalData, - const ui32 indexId, const std::shared_ptr<IStoragesManager>& operators, TSecondaryData& result) const { + const ui32 indexId, const std::shared_ptr<IStoragesManager>& operators, const ui32 recordsCount, TSecondaryData& result) const { auto it = Indexes.find(indexId); AFL_VERIFY(it != Indexes.end()); auto& index = it->second; - std::shared_ptr<IPortionDataChunk> chunk = index->BuildIndex(originalData, *this); + std::shared_ptr<IPortionDataChunk> chunk = index->BuildIndex(originalData, recordsCount, *this); auto opStorage = operators->GetOperatorVerified(index->GetStorageId()); if ((i64)chunk->GetPackedSize() > opStorage->GetBlobSplitSettings().GetMaxBlobSize()) { return TConclusionStatus::Fail("blob size for secondary data (" + ::ToString(indexId) + ") bigger than limit (" + diff --git a/ydb/core/tx/columnshard/engines/scheme/index_info.h b/ydb/core/tx/columnshard/engines/scheme/index_info.h index e4b3534cfd1..eaf4f63eb2e 100644 --- a/ydb/core/tx/columnshard/engines/scheme/index_info.h +++ b/ydb/core/tx/columnshard/engines/scheme/index_info.h @@ -313,11 +313,11 @@ public: }; [[nodiscard]] TConclusion<TSecondaryData> AppendIndexes(const THashMap<ui32, std::vector<std::shared_ptr<IPortionDataChunk>>>& primaryData, - const std::shared_ptr<IStoragesManager>& operators) const { + const std::shared_ptr<IStoragesManager>& operators, const ui32 recordsCount) const { TSecondaryData result; result.MutableExternalData() = primaryData; for (auto&& i : Indexes) { - auto conclusion = AppendIndex(primaryData, i.first, operators, result); + auto conclusion = AppendIndex(primaryData, i.first, operators, recordsCount, result); if (conclusion.IsFail()) { return conclusion; } @@ -329,7 +329,7 @@ public: std::shared_ptr<NIndexes::NCountMinSketch::TIndexMeta> GetIndexMetaCountMinSketch(const std::set<ui32>& columnIds) const; [[nodiscard]] TConclusionStatus AppendIndex(const THashMap<ui32, std::vector<std::shared_ptr<IPortionDataChunk>>>& originalData, - const ui32 indexId, const std::shared_ptr<IStoragesManager>& operators, TSecondaryData& result) const; + const ui32 indexId, const std::shared_ptr<IStoragesManager>& operators, const ui32 recordsCount, TSecondaryData& result) const; /// Returns an id of the column located by name. The name should exists in the schema. ui32 GetColumnIdVerified(const std::string& name) const; diff --git a/ydb/core/tx/columnshard/engines/scheme/indexes/abstract/meta.h b/ydb/core/tx/columnshard/engines/scheme/indexes/abstract/meta.h index d5185cbca23..55c25ace486 100644 --- a/ydb/core/tx/columnshard/engines/scheme/indexes/abstract/meta.h +++ b/ydb/core/tx/columnshard/engines/scheme/indexes/abstract/meta.h @@ -31,7 +31,8 @@ private: YDB_READONLY(ui32, IndexId, 0); YDB_READONLY(TString, StorageId, IStoragesManager::DefaultStorageId); protected: - virtual std::shared_ptr<IPortionDataChunk> DoBuildIndex(const THashMap<ui32, std::vector<std::shared_ptr<IPortionDataChunk>>>& data, const TIndexInfo& indexInfo) const = 0; + virtual std::shared_ptr<IPortionDataChunk> DoBuildIndex(const THashMap<ui32, std::vector<std::shared_ptr<IPortionDataChunk>>>& data, + const ui32 recordsCount, const TIndexInfo& indexInfo) const = 0; virtual void DoFillIndexCheckers(const std::shared_ptr<NRequest::TDataForIndexesCheckers>& info, const NSchemeShard::TOlapSchema& schema) const = 0; virtual bool DoDeserializeFromProto(const NKikimrSchemeOp::TOlapIndexDescription& proto) = 0; virtual void DoSerializeToProto(NKikimrSchemeOp::TOlapIndexDescription& proto) const = 0; @@ -67,8 +68,8 @@ public: virtual ~IIndexMeta() = default; - std::shared_ptr<IPortionDataChunk> BuildIndex(const THashMap<ui32, std::vector<std::shared_ptr<IPortionDataChunk>>>& data, const TIndexInfo& indexInfo) const { - return DoBuildIndex(data, indexInfo); + std::shared_ptr<IPortionDataChunk> BuildIndex(const THashMap<ui32, std::vector<std::shared_ptr<IPortionDataChunk>>>& data, const ui32 recordsCount, const TIndexInfo& indexInfo) const { + return DoBuildIndex(data, recordsCount, indexInfo); } void FillIndexCheckers(const std::shared_ptr<NRequest::TDataForIndexesCheckers>& info, const NSchemeShard::TOlapSchema& schema) const { diff --git a/ydb/core/tx/columnshard/engines/storage/indexes/bloom/checker.h b/ydb/core/tx/columnshard/engines/storage/indexes/bloom/checker.h index 740af9f1720..38fc1031085 100644 --- a/ydb/core/tx/columnshard/engines/storage/indexes/bloom/checker.h +++ b/ydb/core/tx/columnshard/engines/storage/indexes/bloom/checker.h @@ -11,12 +11,39 @@ public: : Data(data) {} + static ui32 GrowBitsCountToByte(const ui32 bitsCount) { + const ui32 bytesCount = bitsCount / 8; + return (bytesCount + ((bitsCount % 8) ? 1 : 0)) * 8; + } + + TFixStringBitsStorage(const std::vector<bool>& bitsVector) + : TFixStringBitsStorage(bitsVector.size()) { + ui32 byteIdx = 0; + ui8 byteCurrent = 0; + ui8 shiftCurrent = 0; + for (ui32 i = 0; i < bitsVector.size(); ++i) { + if (i && i % 8 == 0) { + Data[byteIdx] = (char)byteCurrent; + byteCurrent = 0; + shiftCurrent = 1; + ++byteIdx; + } + if (bitsVector[i]) { + byteCurrent += shiftCurrent; + } + shiftCurrent = (shiftCurrent << 1); + } + if (byteCurrent) { + Data[byteIdx] = (char)byteCurrent; + } + } + ui32 GetSizeBits() const { return Data.size() * 8; } TFixStringBitsStorage(const ui32 sizeBits) - : Data(sizeBits / 8 + ((sizeBits % 8) ? 1 : 0), '\0') { + : Data(GrowBitsCountToByte(sizeBits) / 8, '\0') { } void Set(const bool val, const ui32 idx) { diff --git a/ydb/core/tx/columnshard/engines/storage/indexes/bloom/meta.cpp b/ydb/core/tx/columnshard/engines/storage/indexes/bloom/meta.cpp index e3e3cf7d428..09b09e21dcf 100644 --- a/ydb/core/tx/columnshard/engines/storage/indexes/bloom/meta.cpp +++ b/ydb/core/tx/columnshard/engines/storage/indexes/bloom/meta.cpp @@ -10,26 +10,21 @@ namespace NKikimr::NOlap::NIndexes { -TString TBloomIndexMeta::DoBuildIndexImpl(TChunkedBatchReader& reader) const { - std::set<ui64> hashes; - { - NArrow::NHash::NXX64::TStreamStringHashCalcer hashCalcer(0); +TString TBloomIndexMeta::DoBuildIndexImpl(TChunkedBatchReader& reader, const ui32 recordsCount) const { + const ui32 bitsCount = TFixStringBitsStorage::GrowBitsCountToByte(HashesCount * recordsCount / std::log(2)); + std::vector<bool> filterBits(bitsCount, false); + for (ui32 i = 0; i < HashesCount; ++i) { + NArrow::NHash::NXX64::TStreamStringHashCalcer_H3 hashCalcer(i); for (reader.Start(); reader.IsCorrect(); reader.ReadNext()) { hashCalcer.Start(); for (auto&& i : reader) { NArrow::NHash::TXX64::AppendField(i.GetCurrentChunk(), i.GetCurrentRecordIndex(), hashCalcer); } - hashes.emplace(hashCalcer.Finish()); + filterBits[hashCalcer.Finish() % bitsCount] = true; } } - const ui32 bitsCount = HashesCount * hashes.size() / std::log(2); - TFixStringBitsStorage bits(bitsCount); - const auto pred = [&bits](const ui64 hash) { - bits.Set(true, hash % bits.GetSizeBits()); - }; - BuildHashesSet(hashes, pred); - return bits.GetData(); + return TFixStringBitsStorage(filterBits).GetData(); } void TBloomIndexMeta::DoFillIndexCheckers(const std::shared_ptr<NRequest::TDataForIndexesCheckers>& info, const NSchemeShard::TOlapSchema& schema) const { @@ -51,15 +46,14 @@ void TBloomIndexMeta::DoFillIndexCheckers(const std::shared_ptr<NRequest::TDataF continue; } std::set<ui64> hashes; - const auto pred = [&hashes](const ui64 hash) { - hashes.emplace(hash); - }; - NArrow::NHash::NXX64::TStreamStringHashCalcer calcer(0); - calcer.Start(); - for (auto&& i : foundColumns) { - NArrow::NHash::TXX64::AppendField(i.second, calcer); + for (ui32 i = 0; i < HashesCount; ++i) { + NArrow::NHash::NXX64::TStreamStringHashCalcer_H3 calcer(i); + calcer.Start(); + for (auto&& i : foundColumns) { + NArrow::NHash::TXX64::AppendField(i.second, calcer); + } + hashes.emplace(calcer.Finish()); } - BuildHashesSet(calcer.Finish(), pred); branch->MutableIndexes().emplace_back(std::make_shared<TBloomFilterChecker>(GetIndexId(), std::move(hashes))); } } diff --git a/ydb/core/tx/columnshard/engines/storage/indexes/bloom/meta.h b/ydb/core/tx/columnshard/engines/storage/indexes/bloom/meta.h index ac07cd4793d..cfd9bc85cf2 100644 --- a/ydb/core/tx/columnshard/engines/storage/indexes/bloom/meta.h +++ b/ydb/core/tx/columnshard/engines/storage/indexes/bloom/meta.h @@ -52,7 +52,7 @@ protected: } virtual void DoFillIndexCheckers(const std::shared_ptr<NRequest::TDataForIndexesCheckers>& info, const NSchemeShard::TOlapSchema& schema) const override; - virtual TString DoBuildIndexImpl(TChunkedBatchReader& reader) const override; + virtual TString DoBuildIndexImpl(TChunkedBatchReader& reader, const ui32 recordsCount) const override; virtual bool DoDeserializeFromProto(const NKikimrSchemeOp::TOlapIndexDescription& proto) override { AFL_VERIFY(TBase::DoDeserializeFromProto(proto)); diff --git a/ydb/core/tx/columnshard/engines/storage/indexes/bloom_ngramm/const.cpp b/ydb/core/tx/columnshard/engines/storage/indexes/bloom_ngramm/const.cpp new file mode 100644 index 00000000000..c6b4378157b --- /dev/null +++ b/ydb/core/tx/columnshard/engines/storage/indexes/bloom_ngramm/const.cpp @@ -0,0 +1,19 @@ +#include "const.h" + +#include <util/string/builder.h> + +namespace NKikimr::NOlap::NIndexes::NBloomNGramm { + +TString TConstants::GetHashesCountIntervalString() { + return TStringBuilder() << "[" << MinHashesCount << ", " << MaxHashesCount << "]"; +} + +TString TConstants::GetFilterSizeBytesIntervalString() { + return TStringBuilder() << "[" << MinFilterSizeBytes << ", " << MaxFilterSizeBytes << "]"; +} + +TString TConstants::GetNGrammSizeIntervalString() { + return TStringBuilder() << "[" << MinNGrammSize << ", " << MaxNGrammSize << "]"; +} + +} // namespace NKikimr::NOlap::NIndexes::NBloomNGramm diff --git a/ydb/core/tx/columnshard/engines/storage/indexes/bloom_ngramm/const.h b/ydb/core/tx/columnshard/engines/storage/indexes/bloom_ngramm/const.h new file mode 100644 index 00000000000..1c0e5602880 --- /dev/null +++ b/ydb/core/tx/columnshard/engines/storage/indexes/bloom_ngramm/const.h @@ -0,0 +1,31 @@ +#pragma once +#include <ydb/core/tx/columnshard/engines/scheme/indexes/abstract/constructor.h> +namespace NKikimr::NOlap::NIndexes::NBloomNGramm { + +class TConstants { +public: + static constexpr ui32 MinNGrammSize = 3; + static constexpr ui32 MaxNGrammSize = 8; + static constexpr ui32 MinHashesCount = 1; + static constexpr ui32 MaxHashesCount = 8; + static constexpr ui32 MinFilterSizeBytes = 128; + static constexpr ui32 MaxFilterSizeBytes = 1 << 20; + + static bool CheckNGrammSize(const ui32 value) { + return MinNGrammSize <= value && value <= MaxNGrammSize; + } + + static bool CheckHashesCount(const ui32 value) { + return MinHashesCount <= value && value <= MaxHashesCount; + } + + static bool CheckFilterSizeBytes(const ui32 value) { + return MinFilterSizeBytes <= value && value <= MaxFilterSizeBytes; + } + + static TString GetHashesCountIntervalString(); + static TString GetFilterSizeBytesIntervalString(); + static TString GetNGrammSizeIntervalString(); +}; + +} // namespace NKikimr::NOlap::NIndexes::NBloomNGramm diff --git a/ydb/core/tx/columnshard/engines/storage/indexes/bloom_ngramm/constructor.cpp b/ydb/core/tx/columnshard/engines/storage/indexes/bloom_ngramm/constructor.cpp index e0068eeb21f..5d43b0500df 100644 --- a/ydb/core/tx/columnshard/engines/storage/indexes/bloom_ngramm/constructor.cpp +++ b/ydb/core/tx/columnshard/engines/storage/indexes/bloom_ngramm/constructor.cpp @@ -1,3 +1,4 @@ +#include "const.h" #include "constructor.h" #include "meta.h" @@ -17,7 +18,7 @@ std::shared_ptr<IIndexMeta> TIndexConstructor::DoCreateIndexMeta( HashesCount, FilterSizeBytes, NGrammSize); } -NKikimr::TConclusionStatus TIndexConstructor::DoDeserializeFromJson(const NJson::TJsonValue& jsonInfo) { +TConclusionStatus TIndexConstructor::DoDeserializeFromJson(const NJson::TJsonValue& jsonInfo) { if (!jsonInfo.Has("column_name")) { return TConclusionStatus::Fail("column_name have to be in bloom ngramm filter features"); } @@ -32,24 +33,26 @@ NKikimr::TConclusionStatus TIndexConstructor::DoDeserializeFromJson(const NJson: return TConclusionStatus::Fail("ngramm_size have to be in bloom filter features as uint field"); } NGrammSize = jsonInfo["ngramm_size"].GetUInteger(); - if (NGrammSize < 3 || NGrammSize > 10) { - return TConclusionStatus::Fail("ngramm_size have to be in bloom ngramm filter in interval [3, 10]"); + if (!TConstants::CheckNGrammSize(NGrammSize)) { + return TConclusionStatus::Fail("ngramm_size have to be in bloom ngramm filter in interval " + TConstants::GetNGrammSizeIntervalString()); } if (!jsonInfo["filter_size_bytes"].IsUInteger()) { return TConclusionStatus::Fail("filter_size_bytes have to be in bloom filter features as uint field"); } FilterSizeBytes = jsonInfo["filter_size_bytes"].GetUInteger(); - if (FilterSizeBytes < 128 || FilterSizeBytes > (1 << 20)) { - return TConclusionStatus::Fail("filter_size_bytes have to be in bloom ngramm filter in interval [128, 1Mb]"); + if (!TConstants::CheckFilterSizeBytes(FilterSizeBytes)) { + return TConclusionStatus::Fail( + "filter_size_bytes have to be in bloom ngramm filter in interval " + TConstants::GetFilterSizeBytesIntervalString()); } if (!jsonInfo["hashes_count"].IsUInteger()) { return TConclusionStatus::Fail("hashes_count have to be in bloom filter features as uint field"); } HashesCount = jsonInfo["hashes_count"].GetUInteger(); - if (HashesCount < 1 || HashesCount > 10) { - return TConclusionStatus::Fail("hashes_count have to be in bloom ngramm filter in interval [1, 10]"); + if (!TConstants::CheckHashesCount(HashesCount)) { + return TConclusionStatus::Fail( + "hashes_count have to be in bloom ngramm filter in interval " + TConstants::GetHashesCountIntervalString()); } return TConclusionStatus::Success(); } @@ -62,16 +65,16 @@ NKikimr::TConclusionStatus TIndexConstructor::DoDeserializeFromProto(const NKiki } auto& bFilter = proto.GetBloomNGrammFilter(); NGrammSize = bFilter.GetNGrammSize(); - if (NGrammSize < 3 || NGrammSize > 10) { - return TConclusionStatus::Fail("NGrammSize have to be in [3, 10]"); + if (!TConstants::CheckNGrammSize(NGrammSize)) { + return TConclusionStatus::Fail("NGrammSize have to be in " + TConstants::GetNGrammSizeIntervalString()); } FilterSizeBytes = bFilter.GetFilterSizeBytes(); - if (FilterSizeBytes < 128 || FilterSizeBytes > (1 << 20)) { - return TConclusionStatus::Fail("FilterSizeBytes have to be in [128, 1Mb]"); + if (!TConstants::CheckFilterSizeBytes(FilterSizeBytes)) { + return TConclusionStatus::Fail("FilterSizeBytes have to be in " + TConstants::GetFilterSizeBytesIntervalString()); } HashesCount = bFilter.GetHashesCount(); - if (HashesCount < 1 || HashesCount > 10) { - return TConclusionStatus::Fail("HashesCount size have to be in [3, 10]"); + if (!TConstants::CheckHashesCount(HashesCount)) { + return TConclusionStatus::Fail("HashesCount size have to be in " + TConstants::GetHashesCountIntervalString()); } ColumnName = bFilter.GetColumnName(); if (!ColumnName) { diff --git a/ydb/core/tx/columnshard/engines/storage/indexes/bloom_ngramm/meta.cpp b/ydb/core/tx/columnshard/engines/storage/indexes/bloom_ngramm/meta.cpp index af139065b9c..8511a7914a8 100644 --- a/ydb/core/tx/columnshard/engines/storage/indexes/bloom_ngramm/meta.cpp +++ b/ydb/core/tx/columnshard/engines/storage/indexes/bloom_ngramm/meta.cpp @@ -1,4 +1,5 @@ #include "checker.h" +#include "const.h" #include "meta.h" #include <ydb/core/formats/arrow/hash/calcer.h> @@ -15,42 +16,139 @@ namespace NKikimr::NOlap::NIndexes::NBloomNGramm { class TNGrammBuilder { private: - NArrow::NHash::NXX64::TStreamStringHashCalcer HashCalcer; - TBuffer Zeros; - template <class TAction> - void BuildNGramms(const char* data, const ui32 dataSize, const std::optional<NRequest::TLikePart::EOperation> op, const ui32 nGrammSize, - const TAction& pred) const { - if (!op || op == NRequest::TLikePart::EOperation::StartsWith) { - for (ui32 c = 1; c <= nGrammSize; ++c) { - TBuffer fakeStart; - fakeStart.Fill('\0', nGrammSize - c); - fakeStart.Append(data, std::min(c, dataSize)); - if (fakeStart.size() < nGrammSize) { - fakeStart.Append(Zeros.data(), nGrammSize - fakeStart.size()); + const ui32 HashesCount; + + template <ui32 CharsRemained> + class THashesBuilder { + public: + static ui64 Build(const ui8* data, ui64& h) { + h = h ^ uint64_t(*data); + h = h * 16777619; + return THashesBuilder<CharsRemained - 1>::Build(data + 1, h); + } + }; + + template <> + class THashesBuilder<0> { + public: + static ui64 Build(const ui8* /*data*/, ui64& hash) { + return hash; + } + }; + + template <ui32 HashIdx, ui32 CharsCount> + class THashesCountSelector { + public: + template <class TActor> + static void BuildHashes(const ui8* data, TActor& actor) { + ui64 hash = (ui64)2166136261 * (ui64)HashIdx; + actor(THashesBuilder<CharsCount>::Build(data, hash)); + THashesCountSelector<HashIdx - 1, CharsCount>::BuildHashes(data, actor); + } + }; + + template <ui32 CharsCount> + class THashesCountSelector<0, CharsCount> { + public: + template <class TActor> + static void BuildHashes(const ui8* /*data*/, TActor& /*actor*/) { + } + }; + + template <ui32 HashesCount, ui32 CharsCount> + class THashesSelector { + private: + template <class TActor> + static void BuildHashesImpl( + const ui8* data, const ui32 dataSize, const std::optional<NRequest::TLikePart::EOperation> op, TActor& actor) { + TBuffer fakeString; + if (!op || op == NRequest::TLikePart::EOperation::StartsWith) { + for (ui32 c = 1; c <= CharsCount; ++c) { + fakeString.Clear(); + fakeString.Fill('\0', CharsCount - c); + fakeString.Append((const char*)data, std::min((ui32)c, dataSize)); + if (fakeString.size() < CharsCount) { + fakeString.Fill('\0', CharsCount - fakeString.size()); + } + THashesCountSelector<HashesCount, CharsCount>::BuildHashes((const ui8*)fakeString.data(), actor); + } + } + ui32 c = 0; + for (; c + CharsCount <= dataSize; ++c) { + THashesCountSelector<HashesCount, CharsCount>::BuildHashes(data + c, actor); + } + if (!op || op == NRequest::TLikePart::EOperation::EndsWith) { + for (; c < dataSize; ++c) { + fakeString.Clear(); + fakeString.Append((const char*)data + c, dataSize - c); + fakeString.Fill('\0', CharsCount - fakeString.size()); + THashesCountSelector<HashesCount, CharsCount>::BuildHashes((const ui8*)fakeString.data(), actor); } - pred(fakeStart.data()); } } - for (ui32 c = 0; c < dataSize; ++c) { - if (c + nGrammSize <= dataSize) { - pred(data + c); - } else if (!op || op == NRequest::TLikePart::EOperation::EndsWith) { - TBuffer fakeStart; - fakeStart.Append(data + c, dataSize - c); - fakeStart.Append(Zeros.data(), nGrammSize - fakeStart.size()); - pred(fakeStart.data()); + + public: + template <class TActor> + static void BuildHashes(const ui8* data, const ui32 dataSize, const ui32 hashesCount, const ui32 nGrammSize, + const std::optional<NRequest::TLikePart::EOperation> op, TActor& actor) { + if (HashesCount == hashesCount && CharsCount == nGrammSize) { + BuildHashesImpl(data, dataSize, op, actor); + } else if (HashesCount > hashesCount && CharsCount > nGrammSize) { + THashesSelector<HashesCount - 1, CharsCount - 1>::BuildHashes(data, dataSize, hashesCount, nGrammSize, op, actor); + } else if (HashesCount > hashesCount) { + THashesSelector<HashesCount - 1, CharsCount>::BuildHashes(data, dataSize, hashesCount, nGrammSize, op, actor); + } else if (CharsCount > nGrammSize) { + THashesSelector<HashesCount, CharsCount - 1>::BuildHashes(data, dataSize, hashesCount, nGrammSize, op, actor); + } else { + AFL_VERIFY(false); } } + }; + + template <ui32 CharsCount> + class THashesSelector<0, CharsCount> { + public: + template <class TActor> + static void BuildHashes(const ui8* /*data*/, const ui32 /*dataSize*/, const ui32 /*hashesCount*/, const ui32 /*nGrammSize*/, + const std::optional<NRequest::TLikePart::EOperation> /*op*/, TActor& /*actor*/) { + AFL_VERIFY(false); + } + }; + + template <ui32 HashesCount> + class THashesSelector<HashesCount, 0> { + public: + template <class TActor> + static void BuildHashes(const ui8* /*data*/, const ui32 /*dataSize*/, const ui32 /*hashesCount*/, const ui32 /*nGrammSize*/, + const std::optional<NRequest::TLikePart::EOperation> /*op*/, TActor& /*actor*/) { + AFL_VERIFY(false); + } + }; + + template <> + class THashesSelector<0, 0> { + public: + template <class TActor> + static void BuildHashes(const ui8* /*data*/, const ui32 /*dataSize*/, const ui32 /*hashesCount*/, const ui32 /*nGrammSize*/, + const std::optional<NRequest::TLikePart::EOperation> /*op*/, TActor& /*actor*/) { + AFL_VERIFY(false); + } + }; + + template <class TAction> + void BuildNGramms( + const char* data, const ui32 dataSize, const std::optional<NRequest::TLikePart::EOperation> op, const ui32 nGrammSize, TAction& pred) { + THashesSelector<TConstants::MaxHashesCount, TConstants::MaxNGrammSize>::BuildHashes( + (const ui8*)data, dataSize, HashesCount, nGrammSize, op, pred); } public: - TNGrammBuilder() - : HashCalcer(0) { - Zeros.Fill('\0', 1024); + TNGrammBuilder(const ui32 hashesCount) + : HashesCount(hashesCount) { } template <class TFiller> - void FillNGrammHashes(const ui32 nGrammSize, const std::shared_ptr<arrow::Array>& array, const TFiller& fillData) { + void FillNGrammHashes(const ui32 nGrammSize, const std::shared_ptr<arrow::Array>& array, TFiller& fillData) { AFL_VERIFY(array->type_id() == arrow::utf8()->id())("id", array->type()->ToString()); NArrow::SwitchType(array->type_id(), [&](const auto& type) { using TWrap = std::decay_t<decltype(type)>; @@ -64,15 +162,7 @@ public: } if constexpr (arrow::has_string_view<T>()) { auto value = typedArray.GetView(row); - if (value.size() < nGrammSize) { - continue; - } - const auto pred = [&](const char* data) { - HashCalcer.Start(); - HashCalcer.Update((const ui8*)data, nGrammSize); - fillData(HashCalcer.Finish()); - }; - BuildNGramms(value.data(), value.size(), {}, nGrammSize, pred); + BuildNGramms(value.data(), value.size(), {}, nGrammSize, fillData); } else { AFL_VERIFY(false); } @@ -82,34 +172,38 @@ public: } template <class TFiller> - void FillNGrammHashes(const ui32 nGrammSize, const NRequest::TLikePart::EOperation op, const TString& userReq, const TFiller& fillData) { - const auto pred = [&](const char* value) { - HashCalcer.Start(); - HashCalcer.Update((const ui8*)value, nGrammSize); - fillData(HashCalcer.Finish()); - }; - BuildNGramms(userReq.data(), userReq.size(), op, nGrammSize, pred); + void FillNGrammHashes(const ui32 nGrammSize, const NRequest::TLikePart::EOperation op, const TString& userReq, TFiller& fillData) { + BuildNGramms(userReq.data(), userReq.size(), op, nGrammSize, fillData); } }; -TString TIndexMeta::DoBuildIndexImpl(TChunkedBatchReader& reader) const { - AFL_VERIFY(reader.GetColumnsCount() == 1)("count", reader.GetColumnsCount()); - TNGrammBuilder builder; +class TVectorInserter { +private: + bool* Values; + const ui32 Size; - TFixStringBitsStorage bits(FilterSizeBytes * 8); +public: + TVectorInserter(std::vector<bool>& values) + : Values(&values[0]) + , Size(values.size()) { + } - const auto pred = [&](const ui64 hash) { - const auto predSet = [&](const ui64 hashSecondary) { - bits.Set(true, hashSecondary % bits.GetSizeBits()); - }; - BuildHashesSet(hash, predSet); - }; + void operator()(const ui64 hash) { + Values[hash % Size] = true; + } +}; + +TString TIndexMeta::DoBuildIndexImpl(TChunkedBatchReader& reader, const ui32 /*recordsCount*/) const { + AFL_VERIFY(reader.GetColumnsCount() == 1)("count", reader.GetColumnsCount()); + TNGrammBuilder builder(HashesCount); + + std::vector<bool> bitsVector(FilterSizeBytes * 8, false); + TVectorInserter inserter(bitsVector); for (reader.Start(); reader.IsCorrect();) { - builder.FillNGrammHashes(NGrammSize, reader.begin()->GetCurrentChunk(), pred); + builder.FillNGrammHashes(NGrammSize, reader.begin()->GetCurrentChunk(), inserter); reader.ReadNext(reader.begin()->GetCurrentChunk()->length()); } - - return bits.GetData(); + return TFixStringBitsStorage(bitsVector).GetData(); } void TIndexMeta::DoFillIndexCheckers( @@ -133,16 +227,13 @@ void TIndexMeta::DoFillIndexCheckers( } std::set<ui64> hashes; - const auto pred = [&](const ui64 hash) { - const auto predSet = [&](const ui64 hashSecondary) { - hashes.emplace(hashSecondary); - }; - BuildHashesSet(hash, predSet); + const auto predSet = [&](const ui64 hashSecondary) { + hashes.emplace(hashSecondary); }; - TNGrammBuilder builder; + TNGrammBuilder builder(HashesCount); for (auto&& c : foundColumns) { for (auto&& ls : c.second.GetLikeSequences()) { - builder.FillNGrammHashes(NGrammSize, ls.second.GetOperation(), ls.second.GetValue(), pred); + builder.FillNGrammHashes(NGrammSize, ls.second.GetOperation(), ls.second.GetValue(), predSet); } } branch->MutableIndexes().emplace_back(std::make_shared<TFilterChecker>(GetIndexId(), std::move(hashes))); diff --git a/ydb/core/tx/columnshard/engines/storage/indexes/bloom_ngramm/meta.h b/ydb/core/tx/columnshard/engines/storage/indexes/bloom_ngramm/meta.h index 98af4556a5a..562c0471f1a 100644 --- a/ydb/core/tx/columnshard/engines/storage/indexes/bloom_ngramm/meta.h +++ b/ydb/core/tx/columnshard/engines/storage/indexes/bloom_ngramm/meta.h @@ -23,33 +23,13 @@ private: AFL_VERIFY(NGrammSize > 2); } - static const ui64 HashesConstructorP = ((ui64)2 << 31) - 1; - static const ui64 HashesConstructorA = (ui64)2 << 16; - - template <class TActor> - void BuildHashesSet(const ui64 originalHash, const TActor& actor) const { - AFL_VERIFY(HashesCount < HashesConstructorP); - for (ui32 b = 1; b <= HashesCount; ++b) { - const ui64 hash = (HashesConstructorA * originalHash + b) % HashesConstructorP; - actor(hash); - } - } - - template <class TContainer, class TActor> - void BuildHashesSet(const TContainer& originalHashes, const TActor& actor) const { - AFL_VERIFY(HashesCount < HashesConstructorP); - for (auto&& hOriginal : originalHashes) { - BuildHashesSet(hOriginal, actor); - } - } - protected: virtual TConclusionStatus DoCheckModificationCompatibility(const IIndexMeta& /*newMeta*/) const override { return TConclusionStatus::Fail("not supported"); } virtual void DoFillIndexCheckers(const std::shared_ptr<NRequest::TDataForIndexesCheckers>& info, const NSchemeShard::TOlapSchema& schema) const override; - virtual TString DoBuildIndexImpl(TChunkedBatchReader& reader) const override; + virtual TString DoBuildIndexImpl(TChunkedBatchReader& reader, const ui32 recordsCount) const override; virtual bool DoDeserializeFromProto(const NKikimrSchemeOp::TOlapIndexDescription& proto) override { AFL_VERIFY(TBase::DoDeserializeFromProto(proto)); diff --git a/ydb/core/tx/columnshard/engines/storage/indexes/bloom_ngramm/ya.make b/ydb/core/tx/columnshard/engines/storage/indexes/bloom_ngramm/ya.make index bcba53e477a..ef15149eb3b 100644 --- a/ydb/core/tx/columnshard/engines/storage/indexes/bloom_ngramm/ya.make +++ b/ydb/core/tx/columnshard/engines/storage/indexes/bloom_ngramm/ya.make @@ -4,6 +4,7 @@ SRCS( GLOBAL constructor.cpp GLOBAL meta.cpp GLOBAL checker.cpp + const.cpp ) PEERDIR( diff --git a/ydb/core/tx/columnshard/engines/storage/indexes/count_min_sketch/meta.cpp b/ydb/core/tx/columnshard/engines/storage/indexes/count_min_sketch/meta.cpp index 9e78232d00f..c48b9996964 100644 --- a/ydb/core/tx/columnshard/engines/storage/indexes/count_min_sketch/meta.cpp +++ b/ydb/core/tx/columnshard/engines/storage/indexes/count_min_sketch/meta.cpp @@ -11,7 +11,7 @@ namespace NKikimr::NOlap::NIndexes::NCountMinSketch { -TString TIndexMeta::DoBuildIndexImpl(TChunkedBatchReader& reader) const { +TString TIndexMeta::DoBuildIndexImpl(TChunkedBatchReader& reader, const ui32 /*recordsCount*/) const { auto sketch = std::unique_ptr<TCountMinSketch>(TCountMinSketch::Create()); for (auto& colReader : reader) { diff --git a/ydb/core/tx/columnshard/engines/storage/indexes/count_min_sketch/meta.h b/ydb/core/tx/columnshard/engines/storage/indexes/count_min_sketch/meta.h index 2c23af1fefd..cb7abe56c61 100644 --- a/ydb/core/tx/columnshard/engines/storage/indexes/count_min_sketch/meta.h +++ b/ydb/core/tx/columnshard/engines/storage/indexes/count_min_sketch/meta.h @@ -25,7 +25,7 @@ protected: virtual void DoFillIndexCheckers(const std::shared_ptr<NRequest::TDataForIndexesCheckers>& info, const NSchemeShard::TOlapSchema& schema) const override; - virtual TString DoBuildIndexImpl(TChunkedBatchReader& reader) const override; + virtual TString DoBuildIndexImpl(TChunkedBatchReader& reader, const ui32 recordsCount) const override; virtual bool DoDeserializeFromProto(const NKikimrSchemeOp::TOlapIndexDescription& proto) override { AFL_VERIFY(TBase::DoDeserializeFromProto(proto)); diff --git a/ydb/core/tx/columnshard/engines/storage/indexes/max/meta.cpp b/ydb/core/tx/columnshard/engines/storage/indexes/max/meta.cpp index ac004a9ebab..20cd31857c7 100644 --- a/ydb/core/tx/columnshard/engines/storage/indexes/max/meta.cpp +++ b/ydb/core/tx/columnshard/engines/storage/indexes/max/meta.cpp @@ -9,7 +9,7 @@ namespace NKikimr::NOlap::NIndexes::NMax { -TString TIndexMeta::DoBuildIndexImpl(TChunkedBatchReader& reader) const { +TString TIndexMeta::DoBuildIndexImpl(TChunkedBatchReader& reader, const ui32 /*recordsCount*/) const { std::shared_ptr<arrow::Scalar> result; AFL_VERIFY(reader.GetColumnsCount() == 1)("count", reader.GetColumnsCount()); { diff --git a/ydb/core/tx/columnshard/engines/storage/indexes/max/meta.h b/ydb/core/tx/columnshard/engines/storage/indexes/max/meta.h index 8d760e18428..4c2705bc672 100644 --- a/ydb/core/tx/columnshard/engines/storage/indexes/max/meta.h +++ b/ydb/core/tx/columnshard/engines/storage/indexes/max/meta.h @@ -19,7 +19,7 @@ protected: virtual void DoFillIndexCheckers( const std::shared_ptr<NRequest::TDataForIndexesCheckers>& info, const NSchemeShard::TOlapSchema& schema) const override; - virtual TString DoBuildIndexImpl(TChunkedBatchReader& reader) const override; + virtual TString DoBuildIndexImpl(TChunkedBatchReader& reader, const ui32 recordsCount) const override; virtual bool DoDeserializeFromProto(const NKikimrSchemeOp::TOlapIndexDescription& proto) override { AFL_VERIFY(TBase::DoDeserializeFromProto(proto)); diff --git a/ydb/core/tx/columnshard/engines/storage/indexes/portions/meta.cpp b/ydb/core/tx/columnshard/engines/storage/indexes/portions/meta.cpp index 6fe0e1f2ef1..00c02406358 100644 --- a/ydb/core/tx/columnshard/engines/storage/indexes/portions/meta.cpp +++ b/ydb/core/tx/columnshard/engines/storage/indexes/portions/meta.cpp @@ -6,7 +6,7 @@ namespace NKikimr::NOlap::NIndexes { std::shared_ptr<NKikimr::NOlap::IPortionDataChunk> TIndexByColumns::DoBuildIndex( - const THashMap<ui32, std::vector<std::shared_ptr<IPortionDataChunk>>>& data, const TIndexInfo& indexInfo) const { + const THashMap<ui32, std::vector<std::shared_ptr<IPortionDataChunk>>>& data, const ui32 recordsCount, const TIndexInfo& indexInfo) const { AFL_VERIFY(Serializer); AFL_VERIFY(data.size()); std::vector<TChunkedColumnReader> columnReaders; @@ -15,12 +15,8 @@ std::shared_ptr<NKikimr::NOlap::IPortionDataChunk> TIndexByColumns::DoBuildIndex AFL_VERIFY(it != data.end()); columnReaders.emplace_back(it->second, indexInfo.GetColumnLoaderVerified(i)); } - ui32 recordsCount = 0; - for (auto&& i : data.begin()->second) { - recordsCount += i->GetRecordsCountVerified(); - } TChunkedBatchReader reader(std::move(columnReaders)); - const TString indexData = DoBuildIndexImpl(reader); + const TString indexData = DoBuildIndexImpl(reader, recordsCount); return std::make_shared<NChunks::TPortionIndexChunk>(TChunkAddress(GetIndexId(), 0), recordsCount, indexData.size(), indexData); } diff --git a/ydb/core/tx/columnshard/engines/storage/indexes/portions/meta.h b/ydb/core/tx/columnshard/engines/storage/indexes/portions/meta.h index 5356d5c4302..f8e601c80fc 100644 --- a/ydb/core/tx/columnshard/engines/storage/indexes/portions/meta.h +++ b/ydb/core/tx/columnshard/engines/storage/indexes/portions/meta.h @@ -13,9 +13,10 @@ private: protected: std::set<ui32> ColumnIds; - virtual TString DoBuildIndexImpl(TChunkedBatchReader& reader) const = 0; + virtual TString DoBuildIndexImpl(TChunkedBatchReader& reader, const ui32 recordsCount) const = 0; - virtual std::shared_ptr<IPortionDataChunk> DoBuildIndex(const THashMap<ui32, std::vector<std::shared_ptr<IPortionDataChunk>>>& data, const TIndexInfo& indexInfo) const override final; + virtual std::shared_ptr<IPortionDataChunk> DoBuildIndex(const THashMap<ui32, std::vector<std::shared_ptr<IPortionDataChunk>>>& data, + const ui32 recordsCount, const TIndexInfo& indexInfo) const override final; virtual bool DoDeserializeFromProto(const NKikimrSchemeOp::TOlapIndexDescription& proto) override; TConclusionStatus CheckSameColumnsForModification(const IIndexMeta& newMeta) const; diff --git a/ydb/core/tx/columnshard/splitter/chunks.h b/ydb/core/tx/columnshard/splitter/chunks.h index 35063d0ae80..315fc18604e 100644 --- a/ydb/core/tx/columnshard/splitter/chunks.h +++ b/ydb/core/tx/columnshard/splitter/chunks.h @@ -129,8 +129,7 @@ private: bool IsCorrectFlag = true; public: TChunkedBatchReader(const std::vector<TChunkedColumnReader>& columnReaders) - : Columns(columnReaders) - { + : Columns(columnReaders) { AFL_VERIFY(Columns.size()); for (auto&& i : Columns) { AFL_VERIFY(i.IsCorrect()); diff --git a/ydb/library/formats/arrow/hash/xx_hash.cpp b/ydb/library/formats/arrow/hash/xx_hash.cpp index bc69a160f53..d6b7b654857 100644 --- a/ydb/library/formats/arrow/hash/xx_hash.cpp +++ b/ydb/library/formats/arrow/hash/xx_hash.cpp @@ -2,6 +2,18 @@ namespace NKikimr::NArrow::NHash::NXX64 { +void TStreamStringHashCalcer_H3::Start() { + XXH3_64bits_reset_withSeed(&HashState, Seed); +} + +void TStreamStringHashCalcer_H3::Update(const ui8* data, const ui32 size) { + XXH3_64bits_update(&HashState, data, size); +} + +ui64 TStreamStringHashCalcer_H3::Finish() { + return XXH3_64bits_digest(&HashState); +} + void TStreamStringHashCalcer::Start() { XXH64_reset(&HashState, Seed); } diff --git a/ydb/library/formats/arrow/hash/xx_hash.h b/ydb/library/formats/arrow/hash/xx_hash.h index 25903f47c6d..d0cfed68b54 100644 --- a/ydb/library/formats/arrow/hash/xx_hash.h +++ b/ydb/library/formats/arrow/hash/xx_hash.h @@ -21,4 +21,18 @@ public: ui64 Finish(); }; +class TStreamStringHashCalcer_H3 { +private: + const ui64 Seed; + XXH3_state_t HashState; +public: + TStreamStringHashCalcer_H3(const ui64 seed) + : Seed(seed) { + } + + void Start(); + void Update(const ui8* data, const ui32 size); + ui64 Finish(); +}; + } |
