summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorivanmorozov333 <[email protected]>2024-12-26 15:10:32 +0300
committerGitHub <[email protected]>2024-12-26 15:10:32 +0300
commit2f6245280ebff5279b4ef653f44289857773e562 (patch)
treeed475af18de6d468f446bd532d03ff0b19b2b089
parent24d1f57baa0f092f1c6a5c8bea907380d83962d2 (diff)
bloom ngramms speed up (#12982)
-rw-r--r--ydb/core/formats/arrow/hash/calcer.cpp25
-rw-r--r--ydb/core/formats/arrow/hash/calcer.h2
-rw-r--r--ydb/core/formats/arrow/permutations.cpp1
-rw-r--r--ydb/core/kqp/ut/olap/indexes_ut.cpp12
-rw-r--r--ydb/core/tx/columnshard/engines/changes/compaction/merger.cpp2
-rw-r--r--ydb/core/tx/columnshard/engines/portions/read_with_blobs.cpp2
-rw-r--r--ydb/core/tx/columnshard/engines/reader/common_reader/iterator/fetching.h8
-rw-r--r--ydb/core/tx/columnshard/engines/scheme/index_info.cpp4
-rw-r--r--ydb/core/tx/columnshard/engines/scheme/index_info.h6
-rw-r--r--ydb/core/tx/columnshard/engines/scheme/indexes/abstract/meta.h7
-rw-r--r--ydb/core/tx/columnshard/engines/storage/indexes/bloom/checker.h29
-rw-r--r--ydb/core/tx/columnshard/engines/storage/indexes/bloom/meta.cpp34
-rw-r--r--ydb/core/tx/columnshard/engines/storage/indexes/bloom/meta.h2
-rw-r--r--ydb/core/tx/columnshard/engines/storage/indexes/bloom_ngramm/const.cpp19
-rw-r--r--ydb/core/tx/columnshard/engines/storage/indexes/bloom_ngramm/const.h31
-rw-r--r--ydb/core/tx/columnshard/engines/storage/indexes/bloom_ngramm/constructor.cpp29
-rw-r--r--ydb/core/tx/columnshard/engines/storage/indexes/bloom_ngramm/meta.cpp213
-rw-r--r--ydb/core/tx/columnshard/engines/storage/indexes/bloom_ngramm/meta.h22
-rw-r--r--ydb/core/tx/columnshard/engines/storage/indexes/bloom_ngramm/ya.make1
-rw-r--r--ydb/core/tx/columnshard/engines/storage/indexes/count_min_sketch/meta.cpp2
-rw-r--r--ydb/core/tx/columnshard/engines/storage/indexes/count_min_sketch/meta.h2
-rw-r--r--ydb/core/tx/columnshard/engines/storage/indexes/max/meta.cpp2
-rw-r--r--ydb/core/tx/columnshard/engines/storage/indexes/max/meta.h2
-rw-r--r--ydb/core/tx/columnshard/engines/storage/indexes/portions/meta.cpp8
-rw-r--r--ydb/core/tx/columnshard/engines/storage/indexes/portions/meta.h5
-rw-r--r--ydb/core/tx/columnshard/splitter/chunks.h3
-rw-r--r--ydb/library/formats/arrow/hash/xx_hash.cpp12
-rw-r--r--ydb/library/formats/arrow/hash/xx_hash.h14
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();
+};
+
}