Hi,
Its cover everything, just wanted to run by some points
1. “Rerank fetch Calculated as fetching k × k_multiplier candidates from the
primary index including the preceding key sort.”
k_multiplier occurs still within the VTree, its for fetching k times
k_multiplier from each probe. The cost increases as the number of clusteres
probed.
2. Probe fraction (min_probe_fraction) should also include epsilon which is
used during index creation runtime as that decides how wide the tree is
traversed and along with min_probe decides how many clusters are probed into.
Just adding as this might improve the cbo calculation accuracy.
3. The last one is edge case, although not recommended if vectors are stored in
row based format would the cbo be able to differentiate the selectivity cost
with or without secondary index on the include fields.
Thank you for looking into this!
Regards
Calvin Dani
>
> On Sep 11, 2026, at 3:06 PM, Mike Carey <[email protected]> wrote:
> This sounds like a fantastic 1.0 costing approach!
>
> I don't think the caveats (at the end) are a huge deal - in fact, we are
> thinking we may hold off on exposing cross-pollination in the first release,
> as there seem to be other knobs that can be turned (at least from what
> experiments have shown so far) to achieve comparable performance in recall
> and time - so it doesn't seem justified (at least not yet) to offer that
> knob. (Fewer knobs is better from a user experience standpoint. And it
> seems that there is now an understanding of what to default the other knob
> settings to in order to achieve ~90% recall and nice execution time
> improvement.)
>
> On a tangentially related note - namely expensive AI features and CBO - we
> will need to look at Python UDFs w.r.t. costing them differently than regular
> functions (and predicates and such), which are currently assumed to be free
> and therefore always good to push down.
>
> Cheers,
> Mike
>
> On 9/11/26 9:08 AM, Rithwik Koul wrote:
>> DISCUSS
>> 1. The problem
>> A vector (VTREE) index had no cost. A late rewrite rule looked for the
>> top-k shape
>> LIMIT k → ORDER BY ann_distance(field, $q, metric) → [optional WHERE]
>> → scan
>> and took the first index whose vector field matched, whose similarity
>> metric matched, and whose INCLUDE list covered the predicate fields. It
>> then used that index, unconditionally. Consequences:
>> -
>> An approximate plan ran where an exact one was cheaper.
>> -
>> Two eligible indexes were never compared. First match won; the second
>> candidate was never looked at.
>> -
>> The advisor could only recommend by structure. With no cost, "recommend
>> a vector index" meant "a rule would have matched one", not "it is the
>> cheapest way to answer this".
>> The optimizer's existing index costing could not be borrowed as-is, for two
>> reasons:
>> -
>> it is only entered when the leaf carries a filter, so a WHERE-less ANN
>> query never reached it;
>> -
>> the losing candidates it rejects are communicated through a skip
>> annotation that the ANN rewrite never consulted.
>> 2. What the change does
>> The vector search becomes a third access method competing on cost in the
>> same plan registry as the full scan and the secondary-index scan. The
>> optimizer cost it, compares it against the exact alternatives, keeps the
>> winner, and tells the ANN rewrite rule which indexes it is no longer
>> allowed to use.
>> BEFORE AFTER
>> cost model cost model
>> ├─ table scan ├─ table scan
>> └─ index scan (needs a filter) ├─ index scan (needs a filter)
>> └─ vector scan ◄──
>> rewrite rule rewrite rule
>> └─ first matching vector index └─ honours the optimizer's
>> verdict
>> (never costed, never compared)
>> 3. The cost model3.1 Why the existing index primitive does not fit
>> Every other index cost in the model is driven by selectivity: how much of
>> the collection the predicate keeps. A similarity search does not work that
>> way. It probes a fixed set of clusters and reranks a fixed number of
>> candidates, so its cost barely moves with what the predicate selects. What
>> actually sets it is k, the probe fraction, the rerank multiplier, and the
>> geometry of the index itself. So the vector plan gets its own primitive,
>> parameterized by geometry instead of selectivity.
>> 3.2 Search geometry
>> -
>> A new, self-contained piece of the cost package answers one question:
>> how much of one vector index does one similarity search touch? It derives,
>> per storage partition (each partition searches its own index over its own
>> rows)
>> -
>> Entry width matters only because it decides how many pages a probed
>> cluster spans, so it is derived from what the index actually stores → its
>> primary key, its INCLUDE fields, and how the embedding is represented
>> rather than assumed constant.
>> 3.3 What the vector plan is charged
>> The optimizer's cost object carries six components and collapses to a
>> scalar at comparison time. The vector plan contributes:
>> Charged Component
>> Description & Formula
>> Routing evaluations
>> Charged at one evaluation per centroid encountered while descending the
>> hierarchy.
>> Distance evaluations
>> Charged at one evaluation per entry across all probed clusters.
>> Page reads
>> Covers the physical data pages occupied by the probed clusters.
>> Rerank fetch
>> Calculated as fetching k × k_multiplier candidates from the primary index,
>> including the preceding key sort.
>> 3.4 The decision surface
>> The model was validated over 206 scenarios driven through the real cost
>> classes
>> rerank fetch F = k × k_multiplier, relative to collection size N
>> - F ≲ 0.1·N ──────────────► VECTOR SCAN wins
>> - F ≳ 0.1·N ──────────────► TABLE SCAN wins
>> - predicate selectivity ≲ 0.1–0.3 % on a field that has both a
>> secondary index and an INCLUDE entry ─────► INDEX SCAN wins
>> 4. Selection rules
>> -
>> A tie goes to the exact plan. The vector plan replaces the incumbent
>> only if it is strictly cheaper. An exact answer is never semantically
>> worse
>> than an approximate one, so equal cost means take the exact one.
>> -
>> Between two vector indexes: cheapest first; ties broken by narrower data
>> entries, then by index name, so compilation is deterministic.
>> -
>> Search effort stays user-supplied. The probe fraction and the candidate
>> multiplier trade cost against recall
>> 5. Known modelling gaps
>> Stated deliberately, because they bound how much to trust a verdict:
>> -
>> The vector search cost model currently under-costs execution by ignoring
>> factors such as cross-pollination. This intentional adjustment ensures
>> vector search is generally favored over full scans and B-tree indexes.
>> -
>> The candidate count is assumed unchanged — whereas a selective filter
>> really forces the search to probe further to still return k rows.