enhance: support nullable external id mapping#1673
Conversation
|
@marcelo-cjl 🔍 Important: PR Classification Needed! For efficient project management and a seamless review process, it's essential to classify your PR correctly. Here's how:
For any PR outside the kind/improvement category, ensure you link to the associated issue using the format: “issue: #”. Thanks for your efforts and contribution to the community!. |
b708b6b to
8758e14
Compare
|
I think the ID ownership boundary here needs to be made explicit.
Right now the refiner path mixes the two semantics: the ids are used directly by Can we keep the refiner contract internal-only and move all external/internal conversion to
|
|
The
Can we persist all required source-of-truth fields and rebuild only derived state during
|
|
This may be acceptable for very small datasets, but for large Can we avoid rebuilding this per search? A few options:
|
|
For every non-empty bitset, So filtered search now has an extra O(bitset_size) or O(num_emb_lists) pass per request before the actual index search. That could be significant for large collections and high-QPS filtered workloads, even when Can we either avoid this full count on the hot path or quantify the overhead? Possible approaches:
|
95c9a04 to
b7cf82e
Compare
fce23f6 to
285af48
Compare
285af48 to
8cc525e
Compare
8cc525e to
dda6130
Compare
dda6130 to
3745a01
Compare
39fc115 to
8d65e1b
Compare
8d65e1b to
c71da0e
Compare
c5895e4 to
b141b03
Compare
b141b03 to
8ef741b
Compare
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: marcelo-cjl The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
8ef741b to
af54801
Compare
|
@foxspy Re DataView refiner id boundary: current head keeps |
|
@foxspy Re IdMap wire format: current design changed here. |
|
@foxspy Re BruteForce hot path cost: outdated after the refactor. |
|
@foxspy Re bitset count scan: this is not an extra scan before another scan. Exact-count indexes already need |
af54801 to
01c245e
Compare
|
@marcelo-cjl is this PR ready to be reviewed? |
Signed-off-by: marcelo-cjl <marcelo.chen@zilliz.com>
01c245e to
1e5db0f
Compare
| size_t num_bits_ = 0; | ||
| size_t num_filtered_out_bits_ = 0; | ||
| size_t vector_count_ = 0; | ||
| int64_t filtered_count_ = -1; |
There was a problem hiding this comment.
please make size_t filtered_count_ = 0; instead. I see no reason of it being int64_t
| // optional. many indexes will share one bitset, requiring offset to distinguish between them. | ||
| // like multi-chunk brute-force in /src/common/comp/brute_force.cc, or mv-only in /src/index/hnsw/faiss_hnsw.cc | ||
| size_t id_offset_ = 0; // offset of the internal ids | ||
| int64_t id_offset_ = 0; // offset of the internal ids |
There was a problem hiding this comment.
please make size_t id_offset_ = 0; instead. I see no reason of it being int64_t
| const auto count_bits = std::min(bit_count, num_bits_ - bit_offset); | ||
| const auto end_bit = bit_offset + count_bits; | ||
| size_t bit_pos = bit_offset; | ||
| size_t count = 0; |
There was a problem hiding this comment.
please be consistent with names. If we're counting the future filtered_count_ value, then this variable should be named as filtered_count.
| } | ||
|
|
||
| void | ||
| count_filtered_bits(size_t bit_offset, size_t bit_count, const uint8_t* valid_bitmap = nullptr) { |
There was a problem hiding this comment.
please add a comment on what this function does.
|
|
||
| void | ||
| set_id_offset(size_t id_offset) { | ||
| set_id_offset(int64_t id_offset) { |
There was a problem hiding this comment.
same comment about int64_t
| } | ||
|
|
||
| virtual Status | ||
| FinalizeIdMap() { |
There was a problem hiding this comment.
please add a comment for this function about what it does and how to use it properly
| faiss::cppcontrib::knowhere::HeapBlockResultHandler<CMAX> res(n, distances, labels, k); | ||
| for (auto i = 0; i < n; i++) { | ||
| futs.emplace_back(search_pool->push([&] { | ||
| futs.emplace_back(search_pool->push([&, i = i] { |
There was a problem hiding this comment.
so, you're saying that this DataViewIndexFlat::Search() code has been working incorrectly, because of the missing i=i clause in the futs.emplace_back(search_pool->push([&, i = i] { line.
This is a definite bug that this PR fixes. Same for the similar lines.
| for (int32_t i = 0; i < ann_k; ++i) { | ||
| int64_t doc_id = ann_ids[q * ann_k + i]; | ||
| if (doc_id >= 0 && doc_id < num_docs_) { | ||
| int64_t doc_id = to_in_list_id(ann_ids[q * ann_k + i]); |
There was a problem hiding this comment.
doc_id < num_docs_ condition is gone
| for (int32_t i = 0; i < ann_k; ++i) { | ||
| int64_t doc_id = ann_ids[q * ann_k + i]; | ||
| if (doc_id >= 0 && doc_id < num_docs_) { | ||
| int64_t doc_id = to_in_list_id(ann_ids[q * ann_k + i]); |
| return Status::success; | ||
| void | ||
| PrepareBitsetForSubIndex(BitsetView& bitset, size_t index_id) const { | ||
| const auto& out_ids = bitset_out_ids_[index_id]; |
There was a problem hiding this comment.
does this code preserve mv-related logic?
issue: #1687
related: zilliztech/cardinal#859
related: zilliztech/cardinal#860
Summary
Verification
make pre-commitcmake --build build/Release --target knowhere_tests -j 8build/Release/tests/ut/knowhere_tests "Test_AiSAQ_Params"build/Release/tests/ut/knowhere_tests "Nullable TokenANN GetEmbListByIds uses logical ids"