BIN_IVF_FLAT is an inverted-file (IVF) index for binary vectors. It accelerates similarity search by partitioning your binary vector space into nlist buckets (clusters). At query time, Dodil searches only the most relevant buckets and then does a flat (exact) comparison inside those buckets.
This is a good default when you need faster binary search than a full scan, while keeping behavior simple and predictable.
When to use it
Use BIN_IVF_FLAT when:
- Your embedding field is binary (e.g., perceptual hashes, binary signatures).
- You want a strong balance between speed and recall.
- You prefer a straightforward index that is easy to tune.
Typical binary use cases:
- Near-duplicate detection (images, documents, frames)
- Similarity lookup for perceptual hashes
- Binary embeddings / compact signatures
How it works
- Index build: vectors are grouped into
nlistclusters (buckets). - Search: Dodil selects the top
nprobebuckets relevant to your query. - Exact scan: a flat comparison runs only within those selected buckets.
Two knobs matter most:
nlist: how many buckets existnprobe: how many buckets to search per query
Supported metrics (binary)
Common metrics for binary vectors:
HAMMINGJACCARD
Pick the one that matches how your binary vectors are produced.
Create the index
Below is a typical flow using the Dodil SDK.
from dodil import Client
from dodil.vbase import VBaseConfig
# Authorize
c = Client(
service_account_id="...",
service_account_secret="...",
)
# Connect to VBase
vbase = c.vbase.connect(
VBaseConfig(
host="vbase-db-<id>.infra.dodil.cloud",
port=443,
scheme="https",
db_name="db_<id>",
)
)
# Create a BIN_IVF_FLAT index on a binary vector field
vbase.create_index(
collection_name="my_collection",
field_name="binary_vector",
index_name="binary_vector_index",
index_type="BIN_IVF_FLAT",
metric_type="HAMMING",
params={
"nlist": 128,
},
)Index parameters
nlist(integer)- What it is: number of buckets (clusters)
- Effect:
- higher
nlist→ smaller buckets → better pruning potential, but more build/metadata cost - lower
nlist→ larger buckets → faster build, less pruning
- higher
Practical starting points:
- Small datasets:
nlist = 64or128 - Medium datasets:
nlist = 256to1024
Tip: if you’re unsure, start with
nlist = 128and tune from there.
Search with BIN_IVF_FLAT
Once the index is built, tune query performance with nprobe.
results = vbase.search(
collection_name="my_collection",
anns_field="binary_vector",
data=[query_binary_vector],
limit=10,
search_params={
"params": {
"nprobe": 8
}
},
)
print(results)Search parameters
nprobe(integer)- What it is: how many buckets to search
- Valid range:
1 .. nlist - Effect:
- higher
nprobe→ better recall, higher latency - lower
nprobe→ faster, but may miss neighbors
- higher
Practical starting point:
- If
nlist = 128, trynprobe = 8. - If recall isn’t good enough, increase gradually:
8 → 16 → 32.
Tuning recommendations
If you want faster search
- Keep
nprobelow (e.g.,4–8) - Use a moderate
nlist(e.g.,128–512)
If you want higher recall
- Increase
nprobe(e.g.,16–64) - If buckets are too large, increase
nlist(watch index build time)
Common gotchas
- Partitions vs. parallelism: Partitions (Kafka) and vector index partitions are unrelated—
nlistcontrols vector search bucketing. - Index build time: Bigger
nlistincreases build and resource usage. - Field type must be binary: Ensure your field is a binary vector field (not dense float vectors).
Next: If you haven’t already, learn how to load and release collections for predictable performance in production.