diff --git a/sql/sql_queue.h b/sql/sql_queue.h index d7d16ea26fe..25fe8cc36fa 100644 --- a/sql/sql_queue.h +++ b/sql/sql_queue.h @@ -44,6 +44,11 @@ public: Element *top() const { return (Element*)queue_top(&m_queue); } void push(const Element *element) { queue_insert(&m_queue, (uchar*)element); } + void safe_push(const Element *element) + { + if (is_full()) m_queue.elements--; // remove one of the furthest elements + queue_insert(&m_queue, (uchar*)element); + } Element *pop() { return (Element *)queue_remove_top(&m_queue); } void clear() { queue_remove_all(&m_queue); } void propagate_top() { queue_replace_top(&m_queue); } diff --git a/sql/vector_mhnsw.cc b/sql/vector_mhnsw.cc index f2fd74e0ccb..1564d106b79 100644 --- a/sql/vector_mhnsw.cc +++ b/sql/vector_mhnsw.cc @@ -27,6 +27,7 @@ ulonglong mhnsw_cache_size; // Algorithm parameters static constexpr float alpha = 1.1f; +static constexpr float generosity = 1.1f; static constexpr uint ef_construction= 10; enum Graph_table_fields { @@ -928,7 +929,8 @@ static int search_layer(MHNSW_Context *ctx, TABLE *graph, const FVector *target, best.push(v); } - float furthest_best= FLT_MAX; + float furthest_best= best.is_empty() ? FLT_MAX + : best.top()->distance_to_target * generosity; while (candidates.elements()) { const Visited &cur= *candidates.pop(); @@ -958,15 +960,18 @@ static int search_layer(MHNSW_Context *ctx, TABLE *graph, const FVector *target, if (skip_deleted && v->node->deleted) continue; best.push(v); - furthest_best= best.top()->distance_to_target; + furthest_best= best.top()->distance_to_target * generosity; } else if (v->distance_to_target < furthest_best) { - candidates.push(v); + candidates.safe_push(v); if (skip_deleted && v->node->deleted) continue; - best.replace_top(v); - furthest_best= best.top()->distance_to_target; + if (v->distance_to_target < best.top()->distance_to_target) + { + best.replace_top(v); + furthest_best= best.top()->distance_to_target * generosity; + } } } }