Push down the limit operator to segcore (#25959)

Signed-off-by: longjiquan <jiquan.long@zilliz.com>
This commit is contained in:
Jiquan Long 2023-08-01 20:29:05 +08:00 committed by GitHub
parent 0facefa665
commit 5c1f79dc54
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 582 additions and 274 deletions

View File

@ -123,8 +123,12 @@ if (LINUX OR MSYS)
"-DELPP_THREAD_SAFE"
"-fopenmp"
"-Werror"
"-O3"
)
if (CMAKE_BUILD_TYPE STREQUAL "Release")
append_flags( CMAKE_CXX_FLAGS
"-O3"
)
endif()
endif ()
if ( APPLE )

View File

@ -282,6 +282,7 @@ PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORIT
PROTOBUF_CONSTEXPR QueryPlanNode::QueryPlanNode(
::_pbi::ConstantInitialized): _impl_{
/*decltype(_impl_.predicates_)*/nullptr
, /*decltype(_impl_.limit_)*/int64_t{0}
, /*decltype(_impl_.is_count_)*/false
, /*decltype(_impl_._cached_size_)*/{}} {}
struct QueryPlanNodeDefaultTypeInternal {
@ -492,6 +493,7 @@ const uint32_t TableStruct_plan_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(pro
~0u, // no _inlined_string_donated_
PROTOBUF_FIELD_OFFSET(::milvus::proto::plan::QueryPlanNode, _impl_.predicates_),
PROTOBUF_FIELD_OFFSET(::milvus::proto::plan::QueryPlanNode, _impl_.is_count_),
PROTOBUF_FIELD_OFFSET(::milvus::proto::plan::QueryPlanNode, _impl_.limit_),
~0u, // no _has_bits_
PROTOBUF_FIELD_OFFSET(::milvus::proto::plan::PlanNode, _internal_metadata_),
~0u, // no _extensions_
@ -523,7 +525,7 @@ static const ::_pbi::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protode
{ 138, -1, -1, sizeof(::milvus::proto::plan::Expr)},
{ 156, -1, -1, sizeof(::milvus::proto::plan::VectorANNS)},
{ 167, -1, -1, sizeof(::milvus::proto::plan::QueryPlanNode)},
{ 175, -1, -1, sizeof(::milvus::proto::plan::PlanNode)},
{ 176, -1, -1, sizeof(::milvus::proto::plan::PlanNode)},
};
static const ::_pb::Message* const file_default_instances[] = {
@ -625,29 +627,30 @@ const char descriptor_table_protodef_plan_2eproto[] PROTOBUF_SECTION_VARIABLE(pr
"inary\030\001 \001(\010\022\020\n\010field_id\030\002 \001(\003\022+\n\npredica"
"tes\030\003 \001(\0132\027.milvus.proto.plan.Expr\0220\n\nqu"
"ery_info\030\004 \001(\0132\034.milvus.proto.plan.Query"
"Info\022\027\n\017placeholder_tag\030\005 \001(\t\"N\n\rQueryPl"
"Info\022\027\n\017placeholder_tag\030\005 \001(\t\"]\n\rQueryPl"
"anNode\022+\n\npredicates\030\001 \001(\0132\027.milvus.prot"
"o.plan.Expr\022\020\n\010is_count\030\002 \001(\010\"\304\001\n\010PlanNo"
"de\0224\n\013vector_anns\030\001 \001(\0132\035.milvus.proto.p"
"lan.VectorANNSH\000\022-\n\npredicates\030\002 \001(\0132\027.m"
"ilvus.proto.plan.ExprH\000\0221\n\005query\030\004 \001(\0132 "
".milvus.proto.plan.QueryPlanNodeH\000\022\030\n\020ou"
"tput_field_ids\030\003 \003(\003B\006\n\004node*\272\001\n\006OpType\022"
"\013\n\007Invalid\020\000\022\017\n\013GreaterThan\020\001\022\020\n\014Greater"
"Equal\020\002\022\014\n\010LessThan\020\003\022\r\n\tLessEqual\020\004\022\t\n\005"
"Equal\020\005\022\014\n\010NotEqual\020\006\022\017\n\013PrefixMatch\020\007\022\020"
"\n\014PostfixMatch\020\010\022\t\n\005Match\020\t\022\t\n\005Range\020\n\022\006"
"\n\002In\020\013\022\t\n\005NotIn\020\014*G\n\013ArithOpType\022\013\n\007Unkn"
"own\020\000\022\007\n\003Add\020\001\022\007\n\003Sub\020\002\022\007\n\003Mul\020\003\022\007\n\003Div\020"
"\004\022\007\n\003Mod\020\005B3Z1github.com/milvus-io/milvu"
"s/internal/proto/planpbb\006proto3"
"o.plan.Expr\022\020\n\010is_count\030\002 \001(\010\022\r\n\005limit\030\003"
" \001(\003\"\304\001\n\010PlanNode\0224\n\013vector_anns\030\001 \001(\0132\035"
".milvus.proto.plan.VectorANNSH\000\022-\n\npredi"
"cates\030\002 \001(\0132\027.milvus.proto.plan.ExprH\000\0221"
"\n\005query\030\004 \001(\0132 .milvus.proto.plan.QueryP"
"lanNodeH\000\022\030\n\020output_field_ids\030\003 \003(\003B\006\n\004n"
"ode*\272\001\n\006OpType\022\013\n\007Invalid\020\000\022\017\n\013GreaterTh"
"an\020\001\022\020\n\014GreaterEqual\020\002\022\014\n\010LessThan\020\003\022\r\n\t"
"LessEqual\020\004\022\t\n\005Equal\020\005\022\014\n\010NotEqual\020\006\022\017\n\013"
"PrefixMatch\020\007\022\020\n\014PostfixMatch\020\010\022\t\n\005Match"
"\020\t\022\t\n\005Range\020\n\022\006\n\002In\020\013\022\t\n\005NotIn\020\014*G\n\013Arit"
"hOpType\022\013\n\007Unknown\020\000\022\007\n\003Add\020\001\022\007\n\003Sub\020\002\022\007"
"\n\003Mul\020\003\022\007\n\003Div\020\004\022\007\n\003Mod\020\005B3Z1github.com/"
"milvus-io/milvus/internal/proto/planpbb\006"
"proto3"
;
static const ::_pbi::DescriptorTable* const descriptor_table_plan_2eproto_deps[1] = {
&::descriptor_table_schema_2eproto,
};
static ::_pbi::once_flag descriptor_table_plan_2eproto_once;
const ::_pbi::DescriptorTable descriptor_table_plan_2eproto = {
false, false, 3671, descriptor_table_protodef_plan_2eproto,
false, false, 3686, descriptor_table_protodef_plan_2eproto,
"plan.proto",
&descriptor_table_plan_2eproto_once, descriptor_table_plan_2eproto_deps, 1, 19,
schemas, file_default_instances, TableStruct_plan_2eproto::offsets,
@ -5982,6 +5985,7 @@ QueryPlanNode::QueryPlanNode(const QueryPlanNode& from)
QueryPlanNode* const _this = this; (void)_this;
new (&_impl_) Impl_{
decltype(_impl_.predicates_){nullptr}
, decltype(_impl_.limit_){}
, decltype(_impl_.is_count_){}
, /*decltype(_impl_._cached_size_)*/{}};
@ -5989,7 +5993,9 @@ QueryPlanNode::QueryPlanNode(const QueryPlanNode& from)
if (from._internal_has_predicates()) {
_this->_impl_.predicates_ = new ::milvus::proto::plan::Expr(*from._impl_.predicates_);
}
_this->_impl_.is_count_ = from._impl_.is_count_;
::memcpy(&_impl_.limit_, &from._impl_.limit_,
static_cast<size_t>(reinterpret_cast<char*>(&_impl_.is_count_) -
reinterpret_cast<char*>(&_impl_.limit_)) + sizeof(_impl_.is_count_));
// @@protoc_insertion_point(copy_constructor:milvus.proto.plan.QueryPlanNode)
}
@ -5999,6 +6005,7 @@ inline void QueryPlanNode::SharedCtor(
(void)is_message_owned;
new (&_impl_) Impl_{
decltype(_impl_.predicates_){nullptr}
, decltype(_impl_.limit_){int64_t{0}}
, decltype(_impl_.is_count_){false}
, /*decltype(_impl_._cached_size_)*/{}
};
@ -6032,7 +6039,9 @@ void QueryPlanNode::Clear() {
delete _impl_.predicates_;
}
_impl_.predicates_ = nullptr;
_impl_.is_count_ = false;
::memset(&_impl_.limit_, 0, static_cast<size_t>(
reinterpret_cast<char*>(&_impl_.is_count_) -
reinterpret_cast<char*>(&_impl_.limit_)) + sizeof(_impl_.is_count_));
_internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
}
@ -6058,6 +6067,14 @@ const char* QueryPlanNode::_InternalParse(const char* ptr, ::_pbi::ParseContext*
} else
goto handle_unusual;
continue;
// int64 limit = 3;
case 3:
if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 24)) {
_impl_.limit_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
CHK_(ptr);
} else
goto handle_unusual;
continue;
default:
goto handle_unusual;
} // switch
@ -6100,6 +6117,12 @@ uint8_t* QueryPlanNode::_InternalSerialize(
target = ::_pbi::WireFormatLite::WriteBoolToArray(2, this->_internal_is_count(), target);
}
// int64 limit = 3;
if (this->_internal_limit() != 0) {
target = stream->EnsureSpace(target);
target = ::_pbi::WireFormatLite::WriteInt64ToArray(3, this->_internal_limit(), target);
}
if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray(
_internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream);
@ -6123,6 +6146,11 @@ size_t QueryPlanNode::ByteSizeLong() const {
*_impl_.predicates_);
}
// int64 limit = 3;
if (this->_internal_limit() != 0) {
total_size += ::_pbi::WireFormatLite::Int64SizePlusOne(this->_internal_limit());
}
// bool is_count = 2;
if (this->_internal_is_count() != 0) {
total_size += 1 + 1;
@ -6150,6 +6178,9 @@ void QueryPlanNode::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::
_this->_internal_mutable_predicates()->::milvus::proto::plan::Expr::MergeFrom(
from._internal_predicates());
}
if (from._internal_limit() != 0) {
_this->_internal_set_limit(from._internal_limit());
}
if (from._internal_is_count() != 0) {
_this->_internal_set_is_count(from._internal_is_count());
}

View File

@ -3884,6 +3884,7 @@ class QueryPlanNode final :
enum : int {
kPredicatesFieldNumber = 1,
kLimitFieldNumber = 3,
kIsCountFieldNumber = 2,
};
// .milvus.proto.plan.Expr predicates = 1;
@ -3904,6 +3905,15 @@ class QueryPlanNode final :
::milvus::proto::plan::Expr* predicates);
::milvus::proto::plan::Expr* unsafe_arena_release_predicates();
// int64 limit = 3;
void clear_limit();
int64_t limit() const;
void set_limit(int64_t value);
private:
int64_t _internal_limit() const;
void _internal_set_limit(int64_t value);
public:
// bool is_count = 2;
void clear_is_count();
bool is_count() const;
@ -3922,6 +3932,7 @@ class QueryPlanNode final :
typedef void DestructorSkippable_;
struct Impl_ {
::milvus::proto::plan::Expr* predicates_;
int64_t limit_;
bool is_count_;
mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
};
@ -8118,6 +8129,26 @@ inline void QueryPlanNode::set_is_count(bool value) {
// @@protoc_insertion_point(field_set:milvus.proto.plan.QueryPlanNode.is_count)
}
// int64 limit = 3;
inline void QueryPlanNode::clear_limit() {
_impl_.limit_ = int64_t{0};
}
inline int64_t QueryPlanNode::_internal_limit() const {
return _impl_.limit_;
}
inline int64_t QueryPlanNode::limit() const {
// @@protoc_insertion_point(field_get:milvus.proto.plan.QueryPlanNode.limit)
return _internal_limit();
}
inline void QueryPlanNode::_internal_set_limit(int64_t value) {
_impl_.limit_ = value;
}
inline void QueryPlanNode::set_limit(int64_t value) {
_internal_set_limit(value);
// @@protoc_insertion_point(field_set:milvus.proto.plan.QueryPlanNode.limit)
}
// -------------------------------------------------------------------
// PlanNode

View File

@ -58,7 +58,8 @@ struct RetrievePlanNode : PlanNode {
accept(PlanNodeVisitor&) override;
std::optional<ExprPtr> predicate_;
bool is_count;
bool is_count_;
int64_t limit_;
};
} // namespace milvus::query

View File

@ -205,7 +205,7 @@ ProtoParser::RetrievePlanNodeFromProto(
auto plan_node = [&]() -> std::unique_ptr<RetrievePlanNode> {
auto node = std::make_unique<RetrievePlanNode>();
if (plan_node_proto.has_predicates()) { // version before 2023.03.30.
node->is_count = false;
node->is_count_ = false;
auto& predicate_proto = plan_node_proto.predicates();
auto expr_opt = [&]() -> ExprPtr {
return ParseExpr(predicate_proto);
@ -220,7 +220,8 @@ ProtoParser::RetrievePlanNodeFromProto(
}();
node->predicate_ = std::move(expr_opt);
}
node->is_count = query.is_count();
node->is_count_ = query.is_count();
node->limit_ = query.limit();
}
return node;
}();

View File

@ -148,12 +148,12 @@ ExecPlanNodeVisitor::visit(RetrievePlanNode& node) {
auto active_count = segment->get_active_count(timestamp_);
if (active_count == 0 && !node.is_count) {
if (active_count == 0 && !node.is_count_) {
retrieve_result_opt_ = std::move(retrieve_result);
return;
}
if (active_count == 0 && node.is_count) {
if (active_count == 0 && node.is_count_) {
retrieve_result = *(wrap_num_entities(0));
retrieve_result_opt_ = std::move(retrieve_result);
return;
@ -161,7 +161,7 @@ ExecPlanNodeVisitor::visit(RetrievePlanNode& node) {
BitsetType bitset_holder;
// For case that retrieve by expression, bitset will be allocated when expression is being executed.
if (node.is_count) {
if (node.is_count_) {
bitset_holder.resize(active_count);
}
@ -176,27 +176,27 @@ ExecPlanNodeVisitor::visit(RetrievePlanNode& node) {
segment->mask_with_delete(bitset_holder, active_count, timestamp_);
// if bitset_holder is all 1's, we got empty result
if (bitset_holder.all() && !node.is_count) {
if (bitset_holder.all() && !node.is_count_) {
retrieve_result_opt_ = std::move(retrieve_result);
return;
}
if (node.is_count) {
if (node.is_count_) {
auto cnt = bitset_holder.size() - bitset_holder.count();
retrieve_result = *(wrap_num_entities(cnt));
retrieve_result_opt_ = std::move(retrieve_result);
return;
}
BitsetView final_view = bitset_holder;
auto seg_offsets =
GetExprUsePkIndex() && IsTermExpr(node.predicate_.value().get())
? segment->search_ids(
final_view, expr_cached_pk_id_offsets_, timestamp_)
: segment->search_ids(bitset_holder.flip(), timestamp_);
retrieve_result.result_offsets_.assign(
(int64_t*)seg_offsets.data(),
(int64_t*)seg_offsets.data() + seg_offsets.size());
bitset_holder.flip();
if (GetExprUsePkIndex() && IsTermExpr(node.predicate_.value().get())) {
segment->search_ids_filter(
bitset_holder, expr_cached_pk_id_offsets_, timestamp_);
} else {
segment->search_ids_filter(bitset_holder, timestamp_);
}
retrieve_result.result_offsets_ =
segment->find_first(node.limit_, bitset_holder);
retrieve_result_opt_ = std::move(retrieve_result);
}

View File

@ -18,6 +18,7 @@
#include <unordered_map>
#include <utility>
#include <vector>
#include <queue>
#include "TimestampIndex.h"
#include "common/Schema.h"
@ -29,6 +30,12 @@
namespace milvus::segcore {
constexpr int64_t Unlimited = -1;
constexpr int64_t NoLimit = 0;
// If `bitset_count * 100` > `total_count * BruteForceSelectivity`, we use pk index.
// Otherwise, we use bruteforce to retrieve all the pks and then sort them.
constexpr int64_t BruteForceSelectivity = 10;
class OffsetMap {
public:
virtual ~OffsetMap() = default;
@ -44,10 +51,15 @@ class OffsetMap {
virtual bool
empty() const = 0;
using OffsetType = int64_t;
// TODO: in fact, we can retrieve the pk here. Not sure which way is more efficient.
virtual std::vector<OffsetType>
find_first(int64_t limit, const BitsetType& bitset) const = 0;
};
template <typename T>
class OffsetHashMap : public OffsetMap {
class OffsetOrderedMap : public OffsetMap {
public:
std::vector<int64_t>
find(const PkType& pk) const override {
@ -64,7 +76,7 @@ class OffsetHashMap : public OffsetMap {
void
seal() override {
PanicInfo(
"OffsetHashMap used for growing segment could not be sealed.");
"OffsetOrderedMap used for growing segment could not be sealed.");
}
bool
@ -72,8 +84,41 @@ class OffsetHashMap : public OffsetMap {
return map_.empty();
}
std::vector<OffsetType>
find_first(int64_t limit, const BitsetType& bitset) const override {
if (limit == Unlimited || limit == NoLimit) {
limit = map_.size();
}
// TODO: we can't retrieve pk by offset very conveniently.
// Selectivity should be done outside.
return find_first_by_index(limit, bitset);
}
private:
std::unordered_map<T, std::vector<int64_t>> map_;
std::vector<OffsetType>
find_first_by_index(int64_t limit, const BitsetType& bitset) const {
std::vector<int64_t> seg_offsets;
seg_offsets.reserve(limit);
int64_t hit_num = 0; // avoid counting the number everytime.
auto cnt = bitset.count();
for (auto it = map_.begin(); it != map_.end(); it++) {
if (hit_num >= limit || hit_num >= cnt) {
break;
}
for (auto seg_offset : it->second) {
if (bitset[seg_offset]) {
seg_offsets.push_back(seg_offset);
hit_num++;
}
}
}
return seg_offsets;
}
private:
using OrderedMap = std::map<T, std::vector<int64_t>, std::less<>>;
OrderedMap map_;
};
template <typename T>
@ -81,8 +126,7 @@ class OffsetOrderedArray : public OffsetMap {
public:
std::vector<int64_t>
find(const PkType& pk) const override {
if (!is_sealed)
PanicInfo("OffsetOrderedArray could not search before seal");
check_search();
const T& target = std::get<T>(pk);
auto it =
@ -118,6 +162,44 @@ class OffsetOrderedArray : public OffsetMap {
return array_.empty();
}
std::vector<OffsetType>
find_first(int64_t limit, const BitsetType& bitset) const override {
check_search();
if (limit == Unlimited || limit == NoLimit) {
limit = array_.size();
}
// TODO: we can't retrieve pk by offset very conveniently.
// Selectivity should be done outside.
return find_first_by_index(limit, bitset);
}
private:
std::vector<OffsetType>
find_first_by_index(int64_t limit, const BitsetType& bitset) const {
std::vector<int64_t> seg_offsets;
seg_offsets.reserve(limit);
int64_t hit_num = 0; // avoid counting the number everytime.
auto cnt = bitset.count();
for (auto it = array_.begin(); it != array_.end(); it++) {
if (hit_num >= limit || hit_num >= cnt) {
break;
}
if (bitset[it->second]) {
seg_offsets.push_back(it->second);
hit_num++;
}
}
return seg_offsets;
}
void
check_search() const {
AssertInfo(is_sealed,
"OffsetOrderedArray could not search before seal");
}
private:
bool is_sealed = false;
std::vector<std::pair<T, int64_t>> array_;
@ -154,7 +236,7 @@ struct InsertRecord {
std::make_unique<OffsetOrderedArray<int64_t>>();
else
pk2offset_ =
std::make_unique<OffsetHashMap<int64_t>>();
std::make_unique<OffsetOrderedMap<int64_t>>();
break;
}
case DataType::VARCHAR: {
@ -162,8 +244,8 @@ struct InsertRecord {
pk2offset_ = std::make_unique<
OffsetOrderedArray<std::string>>();
else
pk2offset_ =
std::make_unique<OffsetHashMap<std::string>>();
pk2offset_ = std::make_unique<
OffsetOrderedMap<std::string>>();
break;
}
default: {

View File

@ -474,55 +474,6 @@ SegmentGrowingImpl::bulk_subscript(SystemFieldType system_type,
}
}
std::vector<SegOffset>
SegmentGrowingImpl::search_ids(const BitsetType& bitset,
Timestamp timestamp) const {
std::vector<SegOffset> res_offsets;
for (int i = bitset.find_first(); i < bitset.size();
i = bitset.find_next(i)) {
if (i == BitsetType::npos) {
return res_offsets;
}
auto offset = SegOffset(i);
if (insert_record_.timestamps_[offset.get()] <= timestamp) {
res_offsets.push_back(offset);
}
}
return res_offsets;
}
std::vector<SegOffset>
SegmentGrowingImpl::search_ids(const BitsetView& bitset,
Timestamp timestamp) const {
std::vector<SegOffset> res_offsets;
for (int i = 0; i < bitset.size(); ++i) {
if (!bitset.test(i)) {
auto offset = SegOffset(i);
if (insert_record_.timestamps_[offset.get()] <= timestamp) {
res_offsets.push_back(offset);
}
}
}
return res_offsets;
}
std::vector<SegOffset>
SegmentGrowingImpl::search_ids(const BitsetView& bitset,
const std::vector<int64_t>& offsets,
Timestamp timestamp) const {
std::vector<SegOffset> res_offsets;
for (auto& offset : offsets) {
if (!bitset.test(offset)) {
if (insert_record_.timestamps_[offset] <= timestamp) {
res_offsets.push_back(SegOffset(offset));
}
}
}
return res_offsets;
}
std::pair<std::unique_ptr<IdArray>, std::vector<SegOffset>>
SegmentGrowingImpl::search_ids(const IdArray& id_array,
Timestamp timestamp) const {

View File

@ -213,17 +213,6 @@ class SegmentGrowingImpl : public SegmentGrowing {
std::pair<std::unique_ptr<IdArray>, std::vector<SegOffset>>
search_ids(const IdArray& id_array, Timestamp timestamp) const override;
std::vector<SegOffset>
search_ids(const BitsetType& view, Timestamp timestamp) const override;
std::vector<SegOffset>
search_ids(const BitsetView& view, Timestamp timestamp) const override;
std::vector<SegOffset>
search_ids(const BitsetView& view,
const std::vector<int64_t>& offsets,
Timestamp timestamp) const override;
bool
HasIndex(FieldId field_id) const override {
return true;
@ -245,6 +234,11 @@ class SegmentGrowingImpl : public SegmentGrowing {
return true;
}
std::vector<OffsetMap::OffsetType>
find_first(int64_t limit, const BitsetType& bitset) const override {
return insert_record_.pk2offset_->find_first(limit, bitset);
}
protected:
int64_t
num_chunk() const override;
@ -257,6 +251,11 @@ class SegmentGrowingImpl : public SegmentGrowing {
Assert(plan);
}
const ConcurrentVector<Timestamp>&
get_timestamps() const override {
return insert_record_.timestamps_;
}
private:
SegcoreConfig segcore_config_;
SchemaPtr schema_;

View File

@ -84,7 +84,7 @@ SegmentInternalInterface::Retrieve(const query::RetrievePlan* plan,
auto retrieve_results = visitor.get_retrieve_result(*plan->plan_node_);
retrieve_results.segment_ = (void*)this;
if (plan->plan_node_->is_count) {
if (plan->plan_node_->is_count_) {
AssertInfo(retrieve_results.field_data_.size() == 1,
"count result should only have one column");
*results->add_fields_data() = retrieve_results.field_data_[0];
@ -165,7 +165,7 @@ SegmentInternalInterface::get_real_count() const {
#endif
auto plan = std::make_unique<query::RetrievePlan>(get_schema());
plan->plan_node_ = std::make_unique<query::RetrievePlanNode>();
plan->plan_node_->is_count = true;
plan->plan_node_->is_count_ = true;
auto res = Retrieve(plan.get(), MAX_TIMESTAMP);
AssertInfo(res->fields_data().size() == 1,
"count result should only have one column");
@ -178,4 +178,35 @@ SegmentInternalInterface::get_real_count() const {
return res->fields_data()[0].scalars().long_data().data(0);
}
void
SegmentInternalInterface::search_ids_filter(BitsetType& bitset,
Timestamp timestamp) const {
auto& timestamps = get_timestamps();
for (int offset = bitset.find_first(); offset < bitset.size();
offset = bitset.find_next(offset)) {
if (offset == BitsetType::npos) {
return;
}
// You can't see an entity which is inserted after the point when you search.
if (timestamps[offset] > timestamp) {
bitset[offset] = false;
}
}
}
void
SegmentInternalInterface::search_ids_filter(BitsetType& bitset,
const std::vector<int64_t>& offsets,
Timestamp timestamp) const {
BitsetType bitset_copy = bitset;
bitset.reset();
auto& timestamps = get_timestamps();
for (auto& offset : offsets) {
// You can't see an entity which is inserted after the point when you search.
if (bitset_copy[offset] && timestamps[offset] <= timestamp) {
bitset.set(offset, true);
}
}
}
} // namespace milvus::segcore

View File

@ -183,20 +183,20 @@ class SegmentInternalInterface : public SegmentInterface {
virtual int64_t
get_active_count(Timestamp ts) const = 0;
virtual std::vector<SegOffset>
search_ids(const BitsetType& view, Timestamp timestamp) const = 0;
virtual std::vector<SegOffset>
search_ids(const BitsetView& view, Timestamp timestamp) const = 0;
virtual std::vector<SegOffset>
search_ids(const BitsetView& view,
const std::vector<int64_t>& offsets,
Timestamp timestamp) const = 0;
virtual std::pair<std::unique_ptr<IdArray>, std::vector<SegOffset>>
search_ids(const IdArray& id_array, Timestamp timestamp) const = 0;
void
search_ids_filter(BitsetType& bitset, Timestamp timestamp) const;
void
search_ids_filter(BitsetType& bitset,
const std::vector<int64_t>& offsets,
Timestamp timestamp) const;
virtual std::vector<OffsetMap::OffsetType>
find_first(int64_t limit, const BitsetType& bitset) const = 0;
protected:
// internal API: return chunk_data in span
virtual SpanBase
@ -222,6 +222,9 @@ class SegmentInternalInterface : public SegmentInterface {
virtual void
check_search(const query::Plan* plan) const = 0;
virtual const ConcurrentVector<Timestamp>&
get_timestamps() const = 0;
protected:
mutable std::shared_mutex mutex_;
};

View File

@ -1005,51 +1005,6 @@ SegmentSealedImpl::Delete(int64_t reserved_offset, // deprecated
return Status::OK();
}
std::vector<SegOffset>
SegmentSealedImpl::search_ids(const BitsetType& bitset,
Timestamp timestamp) const {
std::vector<SegOffset> dst_offset;
for (int offset = bitset.find_first(); offset < bitset.size();
offset = bitset.find_next(offset)) {
if (offset == BitsetType::npos) {
return dst_offset;
}
if (insert_record_.timestamps_[offset] <= timestamp) {
dst_offset.emplace_back(offset);
}
}
return dst_offset;
}
std::vector<SegOffset>
SegmentSealedImpl::search_ids(const BitsetView& bitset,
Timestamp timestamp) const {
std::vector<SegOffset> dst_offset;
for (int offset = 0; offset < bitset.size(); offset++) {
if (!bitset.test(offset)) {
if (insert_record_.timestamps_[offset] <= timestamp) {
dst_offset.emplace_back(offset);
}
}
}
return dst_offset;
}
std::vector<SegOffset>
SegmentSealedImpl::search_ids(const BitsetView& bitset,
const std::vector<int64_t>& offsets,
Timestamp timestamp) const {
std::vector<SegOffset> dst_offset;
for (auto& offset : offsets) {
if (!bitset.test(offset)) {
if (insert_record_.timestamps_[offset] <= timestamp) {
dst_offset.emplace_back(offset);
}
}
}
return dst_offset;
}
std::string
SegmentSealedImpl::debug() const {
std::string log_str;

View File

@ -110,6 +110,11 @@ class SegmentSealedImpl : public SegmentSealed {
const IdArray* pks,
const Timestamp* timestamps) override;
std::vector<OffsetMap::OffsetType>
find_first(int64_t limit, const BitsetType& bitset) const override {
return insert_record_.pk2offset_->find_first(limit, bitset);
}
protected:
// blob and row_count
SpanBase
@ -139,6 +144,11 @@ class SegmentSealedImpl : public SegmentSealed {
int64_t
get_active_count(Timestamp ts) const override;
const ConcurrentVector<Timestamp>&
get_timestamps() const override {
return insert_record_.timestamps_;
}
private:
template <typename T>
static void
@ -203,17 +213,6 @@ class SegmentSealedImpl : public SegmentSealed {
std::pair<std::unique_ptr<IdArray>, std::vector<SegOffset>>
search_ids(const IdArray& id_array, Timestamp timestamp) const override;
std::vector<SegOffset>
search_ids(const BitsetView& view, Timestamp timestamp) const override;
std::vector<SegOffset>
search_ids(const BitsetView& view,
const std::vector<int64_t>& offsets,
Timestamp timestamp) const override;
std::vector<SegOffset>
search_ids(const BitsetType& view, Timestamp timestamp) const override;
void
LoadVecIndex(const LoadIndexInfo& info);

View File

@ -51,6 +51,8 @@ set(MILVUS_TEST_FILES
test_local_chunk_manager.cpp
test_disk_file_manager_test.cpp
test_integer_overflow.cpp
test_offset_ordered_map.cpp
test_offset_ordered_array.cpp
)
if ( BUILD_DISK_ANN STREQUAL "ON" )

View File

@ -0,0 +1,107 @@
// Copyright (C) 2019-2020 Zilliz. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the License
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
// or implied. See the License for the specific language governing permissions and limitations under the License
#include <gtest/gtest.h>
#include <random>
#include "segcore/InsertRecord.h"
using namespace milvus;
using namespace milvus::segcore;
template <typename T>
class TypedOffsetOrderedArrayTest : public testing::Test {
public:
void
SetUp() override {
er = std::default_random_engine(42);
}
void
TearDown() override {
}
protected:
void
insert(T pk) {
map_.insert(pk, offset_++);
data_.push_back(pk);
std::sort(data_.begin(), data_.end());
}
void
seal() {
map_.seal();
}
std::vector<T>
random_generate(int num) {
std::vector<T> res;
for (int i = 0; i < num; i++) {
if constexpr (std::is_same_v<std::string, T>) {
res.push_back(std::to_string(er()));
} else {
res.push_back(static_cast<T>(er()));
}
}
return res;
}
protected:
int64_t offset_ = 0;
std::vector<T> data_;
milvus::segcore::OffsetOrderedArray<T> map_;
std::default_random_engine er;
};
using TypeOfPks = testing::Types<int64_t, std::string>;
TYPED_TEST_CASE_P(TypedOffsetOrderedArrayTest);
TYPED_TEST_P(TypedOffsetOrderedArrayTest, find_first) {
std::vector<int64_t> offsets;
// not sealed.
ASSERT_ANY_THROW(this->map_.find_first(Unlimited, {}));
// insert 10 entities.
int num = 10;
auto data = this->random_generate(num);
for (const auto& x : data) {
this->insert(x);
}
// seal.
this->seal();
// all is satisfied.
BitsetType all(num);
all.set();
offsets = this->map_.find_first(num / 2, all);
ASSERT_EQ(num / 2, offsets.size());
for (int i = 1; i < offsets.size(); i++) {
ASSERT_TRUE(data[offsets[i - 1]] <= data[offsets[i]]);
}
offsets = this->map_.find_first(Unlimited, all);
ASSERT_EQ(num, offsets.size());
for (int i = 1; i < offsets.size(); i++) {
ASSERT_TRUE(data[offsets[i - 1]] <= data[offsets[i]]);
}
// none is satisfied.
BitsetType none(num);
none.reset();
offsets = this->map_.find_first(num / 2, none);
ASSERT_EQ(0, offsets.size());
offsets = this->map_.find_first(NoLimit, none);
ASSERT_EQ(0, offsets.size());
}
REGISTER_TYPED_TEST_CASE_P(TypedOffsetOrderedArrayTest, find_first);
INSTANTIATE_TYPED_TEST_CASE_P(Prefix, TypedOffsetOrderedArrayTest, TypeOfPks);

View File

@ -0,0 +1,100 @@
// Copyright (C) 2019-2020 Zilliz. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the License
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
// or implied. See the License for the specific language governing permissions and limitations under the License
#include <gtest/gtest.h>
#include <random>
#include "segcore/InsertRecord.h"
using namespace milvus;
using namespace milvus::segcore;
template <typename T>
class TypedOffsetOrderedMapTest : public testing::Test {
public:
void
SetUp() override {
er = std::default_random_engine(42);
}
void
TearDown() override {
}
protected:
void
insert(T pk) {
map_.insert(pk, offset_++);
data_.push_back(pk);
std::sort(data_.begin(), data_.end());
}
std::vector<T>
random_generate(int num) {
std::vector<T> res;
for (int i = 0; i < num; i++) {
if constexpr (std::is_same_v<std::string, T>) {
res.push_back(std::to_string(er()));
} else {
res.push_back(static_cast<T>(er()));
}
}
return res;
}
protected:
int64_t offset_ = 0;
std::vector<T> data_;
milvus::segcore::OffsetOrderedMap<T> map_;
std::default_random_engine er;
};
using TypeOfPks = testing::Types<int64_t, std::string>;
TYPED_TEST_CASE_P(TypedOffsetOrderedMapTest);
TYPED_TEST_P(TypedOffsetOrderedMapTest, find_first) {
std::vector<int64_t> offsets;
// no data.
offsets = this->map_.find_first(Unlimited, {});
ASSERT_EQ(0, offsets.size());
// insert 10 entities.
int num = 10;
auto data = this->random_generate(num);
for (const auto& x : data) {
this->insert(x);
}
// all is satisfied.
BitsetType all(num);
all.set();
offsets = this->map_.find_first(num / 2, all);
ASSERT_EQ(num / 2, offsets.size());
for (int i = 1; i < offsets.size(); i++) {
ASSERT_TRUE(data[offsets[i - 1]] <= data[offsets[i]]);
}
offsets = this->map_.find_first(Unlimited, all);
ASSERT_EQ(num, offsets.size());
for (int i = 1; i < offsets.size(); i++) {
ASSERT_TRUE(data[offsets[i - 1]] <= data[offsets[i]]);
}
// none is satisfied.
BitsetType none(num);
none.reset();
offsets = this->map_.find_first(num / 2, none);
ASSERT_EQ(0, offsets.size());
offsets = this->map_.find_first(NoLimit, none);
ASSERT_EQ(0, offsets.size());
}
REGISTER_TYPED_TEST_CASE_P(TypedOffsetOrderedMapTest, find_first);
INSTANTIATE_TYPED_TEST_CASE_P(Prefix, TypedOffsetOrderedMapTest, TypeOfPks);

View File

@ -159,6 +159,7 @@ message VectorANNS {
message QueryPlanNode {
Expr predicates = 1;
bool is_count = 2;
int64 limit = 3;
};
message PlanNode {

View File

@ -1346,6 +1346,7 @@ func (m *VectorANNS) GetPlaceholderTag() string {
type QueryPlanNode struct {
Predicates *Expr `protobuf:"bytes,1,opt,name=predicates,proto3" json:"predicates,omitempty"`
IsCount bool `protobuf:"varint,2,opt,name=is_count,json=isCount,proto3" json:"is_count,omitempty"`
Limit int64 `protobuf:"varint,3,opt,name=limit,proto3" json:"limit,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@ -1390,6 +1391,13 @@ func (m *QueryPlanNode) GetIsCount() bool {
return false
}
func (m *QueryPlanNode) GetLimit() int64 {
if m != nil {
return m.Limit
}
return 0
}
type PlanNode struct {
// Types that are valid to be assigned to Node:
// *PlanNode_VectorAnns
@ -1522,102 +1530,103 @@ func init() {
func init() { proto.RegisterFile("plan.proto", fileDescriptor_2d655ab2f7683c23) }
var fileDescriptor_2d655ab2f7683c23 = []byte{
// 1542 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x57, 0xcd, 0x72, 0xdc, 0x4a,
0x15, 0x1e, 0xcd, 0xaf, 0x74, 0x34, 0x1e, 0x2b, 0xda, 0xe0, 0x24, 0xdc, 0xd8, 0x88, 0x5b, 0x5c,
0x73, 0xa9, 0xd8, 0x75, 0xb9, 0x97, 0x84, 0x84, 0x0a, 0xf8, 0x37, 0x9e, 0xa9, 0x24, 0xf6, 0xa0,
0x38, 0x5e, 0xb0, 0x51, 0xf5, 0x48, 0x6d, 0x4f, 0x57, 0x34, 0xdd, 0x8a, 0xd4, 0x9a, 0x78, 0x5e,
0x81, 0x1d, 0x0f, 0xc0, 0x8a, 0x05, 0x7b, 0x96, 0x14, 0x55, 0xbc, 0x00, 0x0b, 0x96, 0xec, 0x79,
0x02, 0x8a, 0x17, 0xa0, 0xfa, 0xb4, 0xe6, 0xcf, 0x35, 0x13, 0x8f, 0x21, 0x55, 0xec, 0xba, 0x4f,
0x9f, 0xf3, 0x9d, 0xdf, 0x3e, 0x7d, 0x1a, 0x20, 0x89, 0x09, 0xdf, 0x49, 0x52, 0x21, 0x85, 0x7b,
0x6f, 0xc0, 0xe2, 0x61, 0x9e, 0xe9, 0xdd, 0x8e, 0x3a, 0x78, 0xd0, 0xcc, 0xc2, 0x3e, 0x1d, 0x10,
0x4d, 0xf2, 0x7e, 0x67, 0x40, 0xf3, 0x84, 0x72, 0x9a, 0xb2, 0xf0, 0x82, 0xc4, 0x39, 0x75, 0x1f,
0x82, 0xd9, 0x13, 0x22, 0x0e, 0x86, 0x24, 0xde, 0x30, 0xb6, 0x8c, 0x6d, 0xb3, 0x5d, 0xf2, 0x1b,
0x8a, 0x72, 0x41, 0x62, 0xf7, 0x0b, 0xb0, 0x18, 0x97, 0x4f, 0xbe, 0xc3, 0xd3, 0xf2, 0x96, 0xb1,
0x5d, 0x69, 0x97, 0x7c, 0x13, 0x49, 0xc5, 0xf1, 0x65, 0x2c, 0x88, 0xc4, 0xe3, 0xca, 0x96, 0xb1,
0x6d, 0xa8, 0x63, 0x24, 0xa9, 0xe3, 0x4d, 0x80, 0x4c, 0xa6, 0x8c, 0x5f, 0xe1, 0x79, 0x75, 0xcb,
0xd8, 0xb6, 0xda, 0x25, 0xdf, 0xd2, 0xb4, 0x0b, 0x12, 0x1f, 0xd4, 0xa0, 0x32, 0x24, 0xb1, 0xf7,
0x5b, 0x03, 0xac, 0x5f, 0xe7, 0x34, 0x1d, 0x75, 0xf8, 0xa5, 0x70, 0x5d, 0xa8, 0x4a, 0x91, 0xbc,
0x47, 0x63, 0x2a, 0x3e, 0xae, 0xdd, 0x4d, 0xb0, 0x07, 0x54, 0xa6, 0x2c, 0x0c, 0xe4, 0x28, 0xa1,
0xa8, 0xca, 0xf2, 0x41, 0x93, 0xce, 0x47, 0x09, 0x75, 0x7f, 0x08, 0x6b, 0x19, 0x25, 0x69, 0xd8,
0x0f, 0x12, 0x92, 0x92, 0x41, 0xa6, 0xb5, 0xf9, 0x4d, 0x4d, 0xec, 0x22, 0x4d, 0x31, 0xa5, 0x22,
0xe7, 0x51, 0x10, 0xd1, 0x90, 0x0d, 0x48, 0xbc, 0x51, 0x43, 0x15, 0x4d, 0x24, 0x1e, 0x69, 0x9a,
0xf7, 0x2f, 0x03, 0xe0, 0x50, 0xc4, 0xf9, 0x80, 0xa3, 0x35, 0xf7, 0xc1, 0xbc, 0x64, 0x34, 0x8e,
0x02, 0x16, 0x15, 0x16, 0x35, 0x70, 0xdf, 0x89, 0xdc, 0xe7, 0x60, 0x45, 0x44, 0x12, 0x6d, 0x92,
0x0a, 0x4e, 0xeb, 0xa7, 0x5f, 0xec, 0xcc, 0xc5, 0xbf, 0x88, 0xfc, 0x11, 0x91, 0x44, 0x59, 0xe9,
0x9b, 0x51, 0xb1, 0x72, 0xbf, 0x84, 0x16, 0xcb, 0x82, 0x24, 0x65, 0x03, 0x92, 0x8e, 0x82, 0xf7,
0x74, 0x84, 0x3e, 0x99, 0x7e, 0x93, 0x65, 0x5d, 0x4d, 0x7c, 0x45, 0x47, 0xee, 0x43, 0xb0, 0x58,
0x16, 0x90, 0x5c, 0x8a, 0xce, 0x11, 0x7a, 0x64, 0xfa, 0x26, 0xcb, 0xf6, 0x71, 0xaf, 0x62, 0xc2,
0x69, 0x26, 0x69, 0x14, 0x24, 0x44, 0xf6, 0x37, 0x6a, 0x5b, 0x15, 0x15, 0x13, 0x4d, 0xea, 0x12,
0xd9, 0x77, 0xb7, 0xc1, 0x51, 0x3a, 0x48, 0x2a, 0x99, 0x64, 0x82, 0xa3, 0x96, 0x3a, 0x82, 0xb4,
0x58, 0xd6, 0x1d, 0x93, 0x5f, 0xd1, 0x91, 0xf7, 0xab, 0xb1, 0xcb, 0xc7, 0xd7, 0x49, 0xea, 0x7e,
0x03, 0x55, 0xc6, 0x2f, 0x05, 0xba, 0x6b, 0xdf, 0x74, 0x09, 0x6b, 0x6d, 0x1a, 0x1f, 0x1f, 0x59,
0x15, 0xc0, 0xf1, 0x35, 0xcb, 0x64, 0xf6, 0xdf, 0x02, 0x1c, 0x80, 0x85, 0xe5, 0x88, 0xf2, 0x3f,
0x83, 0xda, 0x50, 0x6d, 0x0a, 0x80, 0xcd, 0x05, 0x00, 0xb3, 0x25, 0xec, 0x6b, 0x6e, 0xef, 0x4f,
0x06, 0xb4, 0xde, 0x71, 0x92, 0x8e, 0x7c, 0xc2, 0xaf, 0x34, 0xd2, 0x2f, 0xc1, 0x0e, 0x51, 0x55,
0xb0, 0xba, 0x41, 0x10, 0x4e, 0xb3, 0xff, 0x63, 0x28, 0x8b, 0xa4, 0xc8, 0xed, 0xfd, 0x05, 0x62,
0x67, 0x09, 0xe6, 0xb5, 0x2c, 0x92, 0xa9, 0xd1, 0x95, 0x3b, 0x19, 0xfd, 0xc7, 0x32, 0xac, 0x1f,
0xb0, 0xcf, 0x6b, 0xf5, 0x57, 0xb0, 0x1e, 0x8b, 0x8f, 0x34, 0x0d, 0x18, 0x0f, 0xe3, 0x3c, 0x63,
0x43, 0x5d, 0x9e, 0xa6, 0xdf, 0x42, 0x72, 0x67, 0x4c, 0x55, 0x8c, 0x79, 0x92, 0xcc, 0x31, 0xea,
0x32, 0x6c, 0x21, 0x79, 0xca, 0xb8, 0x07, 0xb6, 0x46, 0xd4, 0x2e, 0x56, 0x57, 0x73, 0x11, 0x50,
0x46, 0xb7, 0x99, 0x3d, 0xb0, 0xb5, 0x2a, 0x8d, 0x50, 0x5b, 0x11, 0x01, 0x65, 0x70, 0xed, 0xfd,
0xcd, 0x00, 0xfb, 0x50, 0x0c, 0x12, 0x92, 0xea, 0x28, 0x9d, 0x80, 0x13, 0xd3, 0x4b, 0x19, 0xdc,
0x39, 0x54, 0x2d, 0x25, 0x36, 0x73, 0xc5, 0x3b, 0x70, 0x2f, 0x65, 0x57, 0xfd, 0x79, 0xa4, 0xf2,
0x2a, 0x48, 0xeb, 0x28, 0x77, 0x78, 0xb3, 0x5e, 0x2a, 0x2b, 0xd4, 0x8b, 0xf7, 0x07, 0x03, 0xcc,
0x73, 0x9a, 0x0e, 0x3e, 0x4b, 0xc6, 0x9f, 0x42, 0x1d, 0xe3, 0x9a, 0x6d, 0x94, 0xb7, 0x2a, 0xab,
0x04, 0xb6, 0x60, 0x77, 0x1f, 0x81, 0xcd, 0xb2, 0x80, 0xf1, 0x00, 0x9b, 0x5a, 0x91, 0x7d, 0x8b,
0x65, 0x1d, 0xfe, 0x52, 0x11, 0xd4, 0x73, 0x61, 0xe1, 0x9d, 0x42, 0x33, 0xbf, 0x43, 0xf7, 0x0c,
0x74, 0xef, 0xcb, 0x05, 0x2a, 0x26, 0x9c, 0x7a, 0x75, 0x96, 0xe0, 0xcd, 0x78, 0x0c, 0xb5, 0xb0,
0xcf, 0xe2, 0xa8, 0x88, 0xe9, 0xf7, 0x16, 0x08, 0x2a, 0x19, 0x5f, 0x73, 0x79, 0x9b, 0xd0, 0x28,
0xa4, 0x5d, 0x1b, 0x1a, 0x1d, 0x3e, 0x24, 0x31, 0x8b, 0x9c, 0x92, 0xdb, 0x80, 0xca, 0xa9, 0x90,
0x8e, 0xe1, 0xfd, 0xc3, 0x00, 0xd0, 0x57, 0x06, 0x8d, 0x7a, 0x32, 0x63, 0xd4, 0x8f, 0x16, 0x60,
0x4f, 0x59, 0x8b, 0x65, 0x61, 0xd6, 0x4f, 0xa0, 0xaa, 0x0a, 0xe1, 0x36, 0xab, 0x90, 0x49, 0xf9,
0x80, 0xb9, 0x2e, 0x6e, 0xf7, 0x72, 0x1f, 0x90, 0xcb, 0x7b, 0x02, 0xe6, 0x58, 0xd7, 0xbc, 0x13,
0x2d, 0x80, 0xd7, 0xe2, 0x8a, 0x85, 0x24, 0xde, 0xe7, 0x91, 0x63, 0xb8, 0x6b, 0x60, 0x15, 0xfb,
0xb3, 0xd4, 0x29, 0x7b, 0x7f, 0x37, 0x60, 0x4d, 0x0b, 0xee, 0xa7, 0x4c, 0xf6, 0xcf, 0x92, 0xff,
0xb9, 0x32, 0x9e, 0x81, 0x49, 0x14, 0x54, 0x30, 0xe9, 0x63, 0x8f, 0x16, 0x08, 0x17, 0xda, 0xb0,
0x38, 0x1b, 0xa4, 0x50, 0x7d, 0x04, 0x6b, 0xfa, 0x5e, 0x88, 0x84, 0xa6, 0x84, 0x47, 0xab, 0x76,
0xb6, 0x26, 0x4a, 0x9d, 0x69, 0x21, 0xef, 0xf7, 0xc6, 0xb8, 0xc1, 0xa1, 0x12, 0x4c, 0xd9, 0x38,
0xf4, 0xc6, 0x9d, 0x42, 0x5f, 0x5e, 0x25, 0xf4, 0xee, 0xce, 0xcc, 0x15, 0xbc, 0xcd, 0x55, 0x75,
0x0f, 0xff, 0x5a, 0x86, 0x07, 0x73, 0x21, 0x3f, 0x1e, 0x92, 0xf8, 0xf3, 0xf5, 0xe2, 0xff, 0x77,
0xfc, 0x8b, 0x96, 0x54, 0xbd, 0xd3, 0x13, 0x56, 0xbb, 0xd3, 0x13, 0xf6, 0x97, 0x3a, 0x54, 0x31,
0x56, 0xcf, 0xc1, 0x92, 0x34, 0x1d, 0x04, 0xf4, 0x3a, 0x49, 0x8b, 0x48, 0x3d, 0x5c, 0x80, 0x31,
0xee, 0x7a, 0x6a, 0x56, 0x94, 0xe3, 0x0e, 0xf8, 0x02, 0x20, 0x57, 0x49, 0xd0, 0xc2, 0x3a, 0xd5,
0xdf, 0xff, 0x54, 0x8b, 0x51, 0x93, 0x64, 0x3e, 0x69, 0x02, 0x7b, 0x60, 0xf7, 0xd8, 0x54, 0xbe,
0xb2, 0x34, 0x4d, 0xd3, 0x6e, 0xd0, 0x2e, 0xf9, 0xd0, 0x9b, 0xb6, 0x91, 0x43, 0x68, 0x86, 0xfa,
0x75, 0xd1, 0x10, 0xfa, 0x8d, 0x7b, 0xb4, 0x30, 0xd3, 0x93, 0x47, 0xa8, 0x5d, 0xf2, 0xed, 0x70,
0xe6, 0x4d, 0x7a, 0x03, 0x8e, 0xf6, 0x22, 0x55, 0x05, 0xa4, 0x81, 0x74, 0x30, 0x7f, 0xb0, 0xcc,
0x97, 0x49, 0xa9, 0xb5, 0x4b, 0x7e, 0x2b, 0x9f, 0x1f, 0x04, 0xba, 0x70, 0xaf, 0xf0, 0x6a, 0x06,
0xaf, 0x8e, 0x78, 0xde, 0x52, 0xdf, 0x66, 0x01, 0xd7, 0x7b, 0x37, 0x46, 0x0b, 0x09, 0x9b, 0x05,
0xe2, 0xb8, 0x2a, 0x03, 0x3a, 0x24, 0xf1, 0x2c, 0x7e, 0x03, 0xf1, 0x1f, 0x2f, 0xc5, 0x5f, 0x74,
0x4d, 0xda, 0x25, 0xff, 0x41, 0x6f, 0xf9, 0x25, 0x9a, 0xfa, 0xa1, 0xb5, 0xa2, 0x1e, 0xf3, 0x16,
0x3f, 0x26, 0xed, 0x62, 0xea, 0xc7, 0xb4, 0x83, 0xbc, 0x00, 0xc0, 0xe2, 0xd3, 0x50, 0xd6, 0xd2,
0x72, 0x99, 0x0c, 0x95, 0xaa, 0x5c, 0x86, 0x93, 0x09, 0x73, 0x6f, 0x72, 0xab, 0x51, 0x1e, 0x6e,
0xb9, 0xd5, 0xe3, 0x72, 0x09, 0xa7, 0x43, 0xf2, 0x1e, 0xd8, 0x14, 0x27, 0x5e, 0x8d, 0x60, 0x2f,
0x45, 0x98, 0xce, 0xc5, 0x0a, 0x81, 0x4e, 0x76, 0x07, 0x75, 0xa8, 0x2a, 0x51, 0xef, 0x9f, 0x06,
0xc0, 0x05, 0x0d, 0xa5, 0x48, 0xf7, 0x4f, 0x4f, 0xdf, 0x16, 0x33, 0xbf, 0xf6, 0x57, 0x7f, 0xc8,
0xd4, 0xcc, 0xaf, 0x43, 0x32, 0xf7, 0x1b, 0x29, 0xcf, 0xff, 0x46, 0x9e, 0x02, 0x24, 0x29, 0x8d,
0x58, 0x48, 0x24, 0xcd, 0x6e, 0x7b, 0xa6, 0x66, 0x58, 0xdd, 0x5f, 0x00, 0x7c, 0x50, 0x9f, 0x2f,
0xdd, 0xe0, 0xaa, 0x4b, 0x43, 0x39, 0xf9, 0xa1, 0xf9, 0xd6, 0x87, 0xc9, 0x67, 0xed, 0x2b, 0x58,
0x4f, 0x62, 0x12, 0xd2, 0xbe, 0x88, 0x23, 0x9a, 0x06, 0x92, 0x5c, 0x61, 0xbd, 0x5b, 0x7e, 0x6b,
0x86, 0x7c, 0x4e, 0xae, 0xbc, 0x10, 0xd6, 0x10, 0xa0, 0x1b, 0x13, 0x7e, 0x2a, 0x22, 0x7a, 0xc3,
0x5e, 0x63, 0x75, 0x7b, 0xef, 0x83, 0xc9, 0xb2, 0x20, 0x14, 0x39, 0x97, 0xc5, 0x58, 0xdb, 0x60,
0xd9, 0xa1, 0xda, 0x7a, 0xff, 0x36, 0xc0, 0x9c, 0x28, 0xd8, 0x03, 0x7b, 0x88, 0x61, 0x0d, 0x08,
0xe7, 0xd9, 0x27, 0x3a, 0xf7, 0x34, 0xf8, 0x2a, 0x43, 0x5a, 0x66, 0x9f, 0xf3, 0xcc, 0x7d, 0x36,
0x67, 0xe2, 0xa7, 0x9f, 0x1f, 0x25, 0x3a, 0x63, 0xe4, 0xcf, 0xa1, 0x86, 0x41, 0x2a, 0xe2, 0xb9,
0xb5, 0x2c, 0x9e, 0x63, 0x6b, 0xdb, 0x25, 0x5f, 0x0b, 0xa8, 0x5f, 0x9b, 0xc8, 0x65, 0x92, 0xcb,
0x60, 0x9c, 0x69, 0x95, 0xcd, 0xca, 0x76, 0xc5, 0x6f, 0x69, 0xfa, 0x4b, 0x9d, 0xf0, 0x4c, 0x15,
0x10, 0x17, 0x11, 0xfd, 0xfa, 0xcf, 0x06, 0xd4, 0x75, 0x17, 0x9f, 0x9f, 0x35, 0xd6, 0xc1, 0x3e,
0x49, 0x29, 0x91, 0x34, 0x3d, 0xef, 0x13, 0xee, 0x18, 0xae, 0x03, 0xcd, 0x82, 0x70, 0xfc, 0x21,
0x27, 0xb1, 0x53, 0x76, 0x9b, 0x60, 0xbe, 0xa6, 0x59, 0x86, 0xe7, 0x15, 0x1c, 0x46, 0x68, 0x96,
0xe9, 0xc3, 0xaa, 0x6b, 0x41, 0x4d, 0x2f, 0x6b, 0x8a, 0xef, 0x54, 0x48, 0xbd, 0xab, 0x2b, 0xe0,
0x6e, 0x4a, 0x2f, 0xd9, 0xf5, 0x1b, 0x22, 0xc3, 0xbe, 0xd3, 0x50, 0xc0, 0x5d, 0x91, 0xc9, 0x09,
0xc5, 0x54, 0xb2, 0x7a, 0x69, 0xa9, 0x25, 0x76, 0x02, 0x07, 0xdc, 0x3a, 0x94, 0x3b, 0xdc, 0xb1,
0x15, 0xe9, 0x54, 0xc8, 0x0e, 0x77, 0x9a, 0x5f, 0x9f, 0x80, 0x3d, 0xf3, 0xf8, 0x29, 0x07, 0xde,
0xf1, 0xf7, 0x5c, 0x7c, 0xe4, 0x7a, 0xe2, 0xdb, 0x8f, 0xd4, 0x94, 0xd4, 0x80, 0xca, 0xdb, 0xbc,
0xe7, 0x94, 0xd5, 0xe2, 0x4d, 0x1e, 0x3b, 0x15, 0xb5, 0x38, 0x62, 0x43, 0xa7, 0x8a, 0x14, 0x11,
0x39, 0xb5, 0x83, 0x6f, 0x7f, 0xf3, 0xcd, 0x15, 0x93, 0xfd, 0xbc, 0xb7, 0x13, 0x8a, 0xc1, 0xae,
0x0e, 0xf7, 0x63, 0x26, 0x8a, 0xd5, 0x2e, 0xe3, 0x92, 0xa6, 0x9c, 0xc4, 0xbb, 0x98, 0x81, 0x5d,
0x95, 0x81, 0xa4, 0xd7, 0xab, 0xe3, 0xee, 0xdb, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, 0x2e, 0x85,
0x01, 0x1b, 0x43, 0x11, 0x00, 0x00,
// 1554 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x57, 0xcd, 0x6e, 0xdb, 0xc6,
0x13, 0x17, 0x45, 0x7d, 0x90, 0x43, 0x59, 0x66, 0x88, 0x3f, 0xf0, 0x77, 0x92, 0x26, 0x76, 0xd9,
0xa0, 0x71, 0x53, 0xc4, 0x46, 0x9a, 0x34, 0x69, 0x52, 0xa4, 0xf5, 0x67, 0x2c, 0x21, 0x89, 0xad,
0x32, 0x8e, 0x0f, 0xbd, 0x10, 0x2b, 0x72, 0x6d, 0x2d, 0x42, 0xed, 0x32, 0xe4, 0x52, 0xb1, 0x5e,
0xa1, 0xb7, 0x3e, 0x40, 0x4f, 0x3d, 0xf4, 0xde, 0x63, 0x51, 0xa0, 0x2f, 0xd0, 0x43, 0x8f, 0xbd,
0xf7, 0x09, 0x8a, 0xbe, 0x40, 0xb1, 0xbb, 0xd4, 0x97, 0x21, 0xc5, 0x72, 0x1b, 0xa0, 0xb7, 0xdd,
0xd9, 0x99, 0xdf, 0x7c, 0xee, 0xec, 0x2c, 0x40, 0x1c, 0x21, 0xba, 0x16, 0x27, 0x8c, 0x33, 0xe7,
0x52, 0x97, 0x44, 0xbd, 0x2c, 0x55, 0xbb, 0x35, 0x71, 0x70, 0xa5, 0x96, 0x06, 0x1d, 0xdc, 0x45,
0x8a, 0xe4, 0x7e, 0xab, 0x41, 0x6d, 0x0f, 0x53, 0x9c, 0x90, 0xe0, 0x08, 0x45, 0x19, 0x76, 0xae,
0x82, 0xd1, 0x66, 0x2c, 0xf2, 0x7b, 0x28, 0x5a, 0xd2, 0x56, 0xb4, 0x55, 0xa3, 0x51, 0xf0, 0xaa,
0x82, 0x72, 0x84, 0x22, 0xe7, 0x1a, 0x98, 0x84, 0xf2, 0xfb, 0xf7, 0xe4, 0x69, 0x71, 0x45, 0x5b,
0xd5, 0x1b, 0x05, 0xcf, 0x90, 0xa4, 0xfc, 0xf8, 0x38, 0x62, 0x88, 0xcb, 0x63, 0x7d, 0x45, 0x5b,
0xd5, 0xc4, 0xb1, 0x24, 0x89, 0xe3, 0x65, 0x80, 0x94, 0x27, 0x84, 0x9e, 0xc8, 0xf3, 0xd2, 0x8a,
0xb6, 0x6a, 0x36, 0x0a, 0x9e, 0xa9, 0x68, 0x47, 0x28, 0xda, 0x2a, 0x83, 0xde, 0x43, 0x91, 0xfb,
0x8d, 0x06, 0xe6, 0x57, 0x19, 0x4e, 0xfa, 0x4d, 0x7a, 0xcc, 0x1c, 0x07, 0x4a, 0x9c, 0xc5, 0xaf,
0xa4, 0x31, 0xba, 0x27, 0xd7, 0xce, 0x32, 0x58, 0x5d, 0xcc, 0x13, 0x12, 0xf8, 0xbc, 0x1f, 0x63,
0xa9, 0xca, 0xf4, 0x40, 0x91, 0x0e, 0xfb, 0x31, 0x76, 0x3e, 0x80, 0x85, 0x14, 0xa3, 0x24, 0xe8,
0xf8, 0x31, 0x4a, 0x50, 0x37, 0x55, 0xda, 0xbc, 0x9a, 0x22, 0xb6, 0x24, 0x4d, 0x30, 0x25, 0x2c,
0xa3, 0xa1, 0x1f, 0xe2, 0x80, 0x74, 0x51, 0xb4, 0x54, 0x96, 0x2a, 0x6a, 0x92, 0xb8, 0xa3, 0x68,
0xee, 0x9f, 0x1a, 0xc0, 0x36, 0x8b, 0xb2, 0x2e, 0x95, 0xd6, 0x5c, 0x06, 0xe3, 0x98, 0xe0, 0x28,
0xf4, 0x49, 0x98, 0x5b, 0x54, 0x95, 0xfb, 0x66, 0xe8, 0x3c, 0x02, 0x33, 0x44, 0x1c, 0x29, 0x93,
0x44, 0x70, 0xea, 0x9f, 0x5c, 0x5b, 0x9b, 0x88, 0x7f, 0x1e, 0xf9, 0x1d, 0xc4, 0x91, 0xb0, 0xd2,
0x33, 0xc2, 0x7c, 0xe5, 0xdc, 0x80, 0x3a, 0x49, 0xfd, 0x38, 0x21, 0x5d, 0x94, 0xf4, 0xfd, 0x57,
0xb8, 0x2f, 0x7d, 0x32, 0xbc, 0x1a, 0x49, 0x5b, 0x8a, 0xf8, 0x14, 0xf7, 0x9d, 0xab, 0x60, 0x92,
0xd4, 0x47, 0x19, 0x67, 0xcd, 0x1d, 0xe9, 0x91, 0xe1, 0x19, 0x24, 0xdd, 0x94, 0x7b, 0x11, 0x13,
0x8a, 0x53, 0x8e, 0x43, 0x3f, 0x46, 0xbc, 0xb3, 0x54, 0x5e, 0xd1, 0x45, 0x4c, 0x14, 0xa9, 0x85,
0x78, 0xc7, 0x59, 0x05, 0x5b, 0xe8, 0x40, 0x09, 0x27, 0x9c, 0x30, 0x2a, 0xb5, 0x54, 0x24, 0x48,
0x9d, 0xa4, 0xad, 0x01, 0xf9, 0x29, 0xee, 0xbb, 0x5f, 0x0e, 0x5c, 0xde, 0x3d, 0x8d, 0x13, 0xe7,
0x0e, 0x94, 0x08, 0x3d, 0x66, 0xd2, 0x5d, 0xeb, 0xac, 0x4b, 0xb2, 0xd6, 0x46, 0xf1, 0xf1, 0x24,
0xab, 0x00, 0xd8, 0x3d, 0x25, 0x29, 0x4f, 0xff, 0x29, 0xc0, 0x16, 0x98, 0xb2, 0x1c, 0xa5, 0xfc,
0xa7, 0x50, 0xee, 0x89, 0x4d, 0x0e, 0xb0, 0x3c, 0x05, 0x60, 0xbc, 0x84, 0x3d, 0xc5, 0xed, 0xfe,
0xa8, 0x41, 0xfd, 0x25, 0x45, 0x49, 0xdf, 0x43, 0xf4, 0x44, 0x21, 0x7d, 0x01, 0x56, 0x20, 0x55,
0xf9, 0xf3, 0x1b, 0x04, 0xc1, 0x28, 0xfb, 0x1f, 0x41, 0x91, 0xc5, 0x79, 0x6e, 0x2f, 0x4f, 0x11,
0x3b, 0x88, 0x65, 0x5e, 0x8b, 0x2c, 0x1e, 0x19, 0xad, 0x5f, 0xc8, 0xe8, 0x1f, 0x8a, 0xb0, 0xb8,
0x45, 0xde, 0xad, 0xd5, 0x37, 0x61, 0x31, 0x62, 0x6f, 0x70, 0xe2, 0x13, 0x1a, 0x44, 0x59, 0x4a,
0x7a, 0xaa, 0x3c, 0x0d, 0xaf, 0x2e, 0xc9, 0xcd, 0x01, 0x55, 0x30, 0x66, 0x71, 0x3c, 0xc1, 0xa8,
0xca, 0xb0, 0x2e, 0xc9, 0x23, 0xc6, 0x0d, 0xb0, 0x14, 0xa2, 0x72, 0xb1, 0x34, 0x9f, 0x8b, 0x20,
0x65, 0x54, 0x9b, 0xd9, 0x00, 0x4b, 0xa9, 0x52, 0x08, 0xe5, 0x39, 0x11, 0xa4, 0x8c, 0x5c, 0xbb,
0xbf, 0x6a, 0x60, 0x6d, 0xb3, 0x6e, 0x8c, 0x12, 0x15, 0xa5, 0x3d, 0xb0, 0x23, 0x7c, 0xcc, 0xfd,
0x0b, 0x87, 0xaa, 0x2e, 0xc4, 0xc6, 0xae, 0x78, 0x13, 0x2e, 0x25, 0xe4, 0xa4, 0x33, 0x89, 0x54,
0x9c, 0x07, 0x69, 0x51, 0xca, 0x6d, 0x9f, 0xad, 0x17, 0x7d, 0x8e, 0x7a, 0x71, 0xbf, 0xd7, 0xc0,
0x38, 0xc4, 0x49, 0xf7, 0x9d, 0x64, 0xfc, 0x01, 0x54, 0x64, 0x5c, 0xd3, 0xa5, 0xe2, 0x8a, 0x3e,
0x4f, 0x60, 0x73, 0x76, 0xe7, 0x3a, 0x58, 0x24, 0xf5, 0x09, 0xf5, 0x65, 0x53, 0xcb, 0xb3, 0x6f,
0x92, 0xb4, 0x49, 0x9f, 0x08, 0x82, 0x78, 0x2e, 0x4c, 0x79, 0xa7, 0xa4, 0x99, 0xf7, 0xa4, 0x7b,
0x9a, 0x74, 0xef, 0xc6, 0x14, 0x15, 0x43, 0x4e, 0xb5, 0x3a, 0x88, 0xe5, 0xcd, 0xb8, 0x0d, 0xe5,
0xa0, 0x43, 0xa2, 0x30, 0x8f, 0xe9, 0xff, 0xa7, 0x08, 0x0a, 0x19, 0x4f, 0x71, 0xb9, 0xcb, 0x50,
0xcd, 0xa5, 0x1d, 0x0b, 0xaa, 0x4d, 0xda, 0x43, 0x11, 0x09, 0xed, 0x82, 0x53, 0x05, 0x7d, 0x9f,
0x71, 0x5b, 0x73, 0x7f, 0xd7, 0x00, 0xd4, 0x95, 0x91, 0x46, 0xdd, 0x1f, 0x33, 0xea, 0xc3, 0x29,
0xd8, 0x23, 0xd6, 0x7c, 0x99, 0x9b, 0xf5, 0x31, 0x94, 0x44, 0x21, 0x9c, 0x67, 0x95, 0x64, 0x12,
0x3e, 0xc8, 0x5c, 0xe7, 0xb7, 0x7b, 0xb6, 0x0f, 0x92, 0xcb, 0xbd, 0x0f, 0xc6, 0x40, 0xd7, 0xa4,
0x13, 0x75, 0x80, 0x67, 0xec, 0x84, 0x04, 0x28, 0xda, 0xa4, 0xa1, 0xad, 0x39, 0x0b, 0x60, 0xe6,
0xfb, 0x83, 0xc4, 0x2e, 0xba, 0xbf, 0x69, 0xb0, 0xa0, 0x04, 0x37, 0x13, 0xc2, 0x3b, 0x07, 0xf1,
0xbf, 0xae, 0x8c, 0x87, 0x60, 0x20, 0x01, 0xe5, 0x0f, 0xfb, 0xd8, 0xf5, 0x29, 0xc2, 0xb9, 0x36,
0x59, 0x9c, 0x55, 0x94, 0xab, 0xde, 0x81, 0x05, 0x75, 0x2f, 0x58, 0x8c, 0x13, 0x44, 0xc3, 0x79,
0x3b, 0x5b, 0x4d, 0x4a, 0x1d, 0x28, 0x21, 0xf7, 0x3b, 0x6d, 0xd0, 0xe0, 0xa4, 0x12, 0x99, 0xb2,
0x41, 0xe8, 0xb5, 0x0b, 0x85, 0xbe, 0x38, 0x4f, 0xe8, 0x9d, 0xb5, 0xb1, 0x2b, 0x78, 0x9e, 0xab,
0xe2, 0x1e, 0xfe, 0x52, 0x84, 0x2b, 0x13, 0x21, 0xdf, 0xed, 0xa1, 0xe8, 0xdd, 0xf5, 0xe2, 0xff,
0x3a, 0xfe, 0x79, 0x4b, 0x2a, 0x5d, 0xe8, 0x09, 0x2b, 0x5f, 0xe8, 0x09, 0xfb, 0xb9, 0x02, 0x25,
0x19, 0xab, 0x47, 0x60, 0x72, 0x9c, 0x74, 0x7d, 0x7c, 0x1a, 0x27, 0x79, 0xa4, 0xae, 0x4e, 0xc1,
0x18, 0x74, 0x3d, 0x31, 0x2b, 0xf2, 0x41, 0x07, 0x7c, 0x0c, 0x90, 0x89, 0x24, 0x28, 0x61, 0x95,
0xea, 0xf7, 0xde, 0xd6, 0x62, 0xc4, 0x24, 0x99, 0x0d, 0x9b, 0xc0, 0x06, 0x58, 0x6d, 0x32, 0x92,
0xd7, 0x67, 0xa6, 0x69, 0xd4, 0x0d, 0x1a, 0x05, 0x0f, 0xda, 0xa3, 0x36, 0xb2, 0x0d, 0xb5, 0x40,
0xbd, 0x2e, 0x0a, 0x42, 0xbd, 0x71, 0xd7, 0xa7, 0x66, 0x7a, 0xf8, 0x08, 0x35, 0x0a, 0x9e, 0x15,
0x8c, 0xbd, 0x49, 0xcf, 0xc1, 0x56, 0x5e, 0x24, 0xa2, 0x80, 0x14, 0x90, 0x0a, 0xe6, 0xfb, 0xb3,
0x7c, 0x19, 0x96, 0x5a, 0xa3, 0xe0, 0xd5, 0xb3, 0xc9, 0x41, 0xa0, 0x05, 0x97, 0x72, 0xaf, 0xc6,
0xf0, 0x2a, 0x12, 0xcf, 0x9d, 0xe9, 0xdb, 0x38, 0xe0, 0x62, 0xfb, 0xcc, 0x68, 0xc1, 0x61, 0x39,
0x47, 0x1c, 0x54, 0xa5, 0x8f, 0x7b, 0x28, 0x1a, 0xc7, 0xaf, 0x4a, 0xfc, 0xdb, 0x33, 0xf1, 0xa7,
0x5d, 0x93, 0x46, 0xc1, 0xbb, 0xd2, 0x9e, 0x7d, 0x89, 0x46, 0x7e, 0x28, 0xad, 0x52, 0x8f, 0x71,
0x8e, 0x1f, 0xc3, 0x76, 0x31, 0xf2, 0x63, 0xd4, 0x41, 0x1e, 0x03, 0xc8, 0xe2, 0x53, 0x50, 0xe6,
0xcc, 0x72, 0x19, 0x0e, 0x95, 0xa2, 0x5c, 0x7a, 0xc3, 0x09, 0x73, 0x63, 0x78, 0xab, 0xa5, 0x3c,
0x9c, 0x73, 0xab, 0x07, 0xe5, 0x12, 0x8c, 0x86, 0xe4, 0x0d, 0xb0, 0xb0, 0x9c, 0x78, 0x15, 0x82,
0x35, 0x13, 0x61, 0x34, 0x17, 0x0b, 0x04, 0x3c, 0xdc, 0x6d, 0x55, 0xa0, 0x24, 0x44, 0xdd, 0x3f,
0x34, 0x80, 0x23, 0x1c, 0x70, 0x96, 0x6c, 0xee, 0xef, 0xbf, 0xc8, 0x67, 0x7e, 0xe5, 0xaf, 0xfa,
0x90, 0x89, 0x99, 0x5f, 0x85, 0x64, 0xe2, 0x37, 0x52, 0x9c, 0xfc, 0x8d, 0x3c, 0x00, 0x88, 0x13,
0x1c, 0x92, 0x00, 0x71, 0x9c, 0x9e, 0xf7, 0x4c, 0x8d, 0xb1, 0x3a, 0x9f, 0x03, 0xbc, 0x16, 0x9f,
0x2f, 0xd5, 0xe0, 0x4a, 0x33, 0x43, 0x39, 0xfc, 0xa1, 0x79, 0xe6, 0xeb, 0xe1, 0x67, 0xed, 0x26,
0x2c, 0xc6, 0x11, 0x0a, 0x70, 0x87, 0x45, 0x21, 0x4e, 0x7c, 0x8e, 0x4e, 0x64, 0xbd, 0x9b, 0x5e,
0x7d, 0x8c, 0x7c, 0x88, 0x4e, 0xdc, 0x3e, 0x2c, 0x48, 0x80, 0x56, 0x84, 0xe8, 0x3e, 0x0b, 0xf1,
0x19, 0x7b, 0xb5, 0xf9, 0xed, 0xbd, 0x0c, 0x06, 0x49, 0xfd, 0x80, 0x65, 0x94, 0xe7, 0x63, 0x6d,
0x95, 0xa4, 0xdb, 0x62, 0xeb, 0xfc, 0x0f, 0xca, 0x11, 0xe9, 0x12, 0xf5, 0x4a, 0xeb, 0x9e, 0xda,
0xb8, 0x7f, 0x69, 0x60, 0x0c, 0xd5, 0x6e, 0x80, 0xd5, 0x93, 0xc1, 0xf6, 0x11, 0xa5, 0xe9, 0x5b,
0xfa, 0xf9, 0x28, 0x25, 0x22, 0x6f, 0x4a, 0x66, 0x93, 0xd2, 0xd4, 0x79, 0x38, 0x61, 0xf8, 0xdb,
0x1f, 0x25, 0x21, 0x3a, 0x66, 0xfa, 0x67, 0x50, 0x96, 0xa1, 0xcb, 0xa3, 0xbc, 0x32, 0x2b, 0xca,
0x03, 0x6b, 0x1b, 0x05, 0x4f, 0x09, 0x88, 0xbf, 0x1c, 0xcb, 0x78, 0x9c, 0x71, 0x7f, 0x90, 0x7f,
0x91, 0x63, 0x7d, 0x55, 0xf7, 0xea, 0x8a, 0xfe, 0x44, 0x95, 0x41, 0x2a, 0xca, 0x8a, 0xb2, 0x10,
0xdf, 0xfa, 0x49, 0x83, 0x8a, 0xea, 0xed, 0x93, 0x13, 0xc8, 0x22, 0x58, 0x7b, 0x09, 0x46, 0x1c,
0x27, 0x87, 0x1d, 0x44, 0x6d, 0xcd, 0xb1, 0xa1, 0x96, 0x13, 0x76, 0x5f, 0x67, 0x28, 0xb2, 0x8b,
0x4e, 0x0d, 0x8c, 0x67, 0x38, 0x4d, 0xe5, 0xb9, 0x2e, 0x47, 0x14, 0x9c, 0xa6, 0xea, 0xb0, 0xe4,
0x98, 0x50, 0x56, 0xcb, 0xb2, 0xe0, 0xdb, 0x67, 0x5c, 0xed, 0x2a, 0x02, 0xb8, 0x95, 0xe0, 0x63,
0x72, 0xfa, 0x1c, 0xf1, 0xa0, 0x63, 0x57, 0x05, 0x70, 0x8b, 0xa5, 0x7c, 0x48, 0x31, 0x84, 0xac,
0x5a, 0x9a, 0x62, 0x29, 0xfb, 0x83, 0x0d, 0x4e, 0x05, 0x8a, 0x4d, 0x6a, 0x5b, 0x82, 0xb4, 0xcf,
0x78, 0x93, 0xda, 0xb5, 0x5b, 0x7b, 0x60, 0x8d, 0x3d, 0x89, 0xc2, 0x81, 0x97, 0xf4, 0x15, 0x65,
0x6f, 0xa8, 0x9a, 0x03, 0x37, 0x43, 0x31, 0x3b, 0x55, 0x41, 0x7f, 0x91, 0xb5, 0xed, 0xa2, 0x58,
0x3c, 0xcf, 0x22, 0x5b, 0x17, 0x8b, 0x1d, 0xd2, 0xb3, 0x4b, 0x92, 0xc2, 0x42, 0xbb, 0xbc, 0x75,
0xf7, 0xeb, 0x3b, 0x27, 0x84, 0x77, 0xb2, 0xf6, 0x5a, 0xc0, 0xba, 0xeb, 0x2a, 0xdc, 0xb7, 0x09,
0xcb, 0x57, 0xeb, 0x84, 0x72, 0x9c, 0x50, 0x14, 0xad, 0xcb, 0x0c, 0xac, 0x8b, 0x0c, 0xc4, 0xed,
0x76, 0x45, 0xee, 0xee, 0xfe, 0x1d, 0x00, 0x00, 0xff, 0xff, 0x38, 0x9d, 0xc7, 0x85, 0x59, 0x11,
0x00, 0x00,
}

View File

@ -321,6 +321,7 @@ func (t *queryTask) PreExecute(ctx context.Context) error {
if err := t.createPlan(ctx); err != nil {
return err
}
t.plan.Node.(*planpb.PlanNode_Query).Query.Limit = t.RetrieveRequest.Limit
partitionNames := t.request.GetPartitionNames()
if t.partitionKeyMode {

View File

@ -28,7 +28,6 @@ import "C"
import (
"context"
"fmt"
"sort"
"sync"
"unsafe"
@ -459,7 +458,8 @@ func (s *LocalSegment) Retrieve(ctx context.Context, plan *RetrievePlan) (*segco
zap.Int("resultNum", len(result.Offset)),
)
sort.Sort(&byPK{result})
// Sort was done by the segcore.
// sort.Sort(&byPK{result})
return result, nil
}