Optional sparse full scan threshold (#3116)

* optional sparse full scan threshold

* update openapi

* skip serializing if none

* review remarks
This commit is contained in:
Ivan Pleshkov
2023-11-30 21:47:30 +01:00
committed by generall
parent 684c58fbdc
commit ee7a165d9b
6 changed files with 17 additions and 10 deletions

View File

@@ -10543,15 +10543,13 @@
},
"SparseIndexConfig": {
"type": "object",
"required": [
"full_scan_threshold"
],
"properties": {
"full_scan_threshold": {
"description": "We prefer a full scan search upto (excluding) this number of vectors.\n\nNote: this is number of vectors, not KiloBytes.",
"type": "integer",
"format": "uint",
"minimum": 0
"minimum": 0,
"nullable": true
},
"on_disk": {
"description": "Store index on disk. If set to false, the index will be stored in RAM. Default: false",

View File

@@ -64,7 +64,7 @@ fn sparse_vector_index_build_benchmark(c: &mut Criterion) {
drop(borrowed_storage);
// save index config to disk
let index_config = SparseIndexConfig::new(10_000, None);
let index_config = SparseIndexConfig::new(Some(10_000), None);
// intent: measure in-memory build time from storage
group.bench_function("build-ram-index", |b| {

View File

@@ -46,7 +46,7 @@ pub fn fixture_open_sparse_index<I: InvertedIndex>(
let db = open_db(storage_dir, &[DB_VECTOR_CF]).unwrap();
let vector_storage = open_simple_sparse_vector_storage(db, DB_VECTOR_CF)?;
let sparse_index_config = SparseIndexConfig::new(full_scan_threshold, None);
let sparse_index_config = SparseIndexConfig::new(Some(full_scan_threshold), None);
let sparse_vector_index: SparseVectorIndex<I> = SparseVectorIndex::open(
sparse_index_config,
id_tracker,

View File

@@ -15,8 +15,10 @@ pub struct SparseIndexConfig {
/// We prefer a full scan search upto (excluding) this number of vectors.
///
/// Note: this is number of vectors, not KiloBytes.
pub full_scan_threshold: usize,
#[serde(skip_serializing_if = "Option::is_none")]
pub full_scan_threshold: Option<usize>,
/// Store index on disk. If set to false, the index will be stored in RAM. Default: false
#[serde(skip_serializing_if = "Option::is_none")]
pub on_disk: Option<bool>,
}
@@ -30,7 +32,7 @@ impl Anonymize for SparseIndexConfig {
}
impl SparseIndexConfig {
pub fn new(full_scan_threshold: usize, on_disk: Option<bool>) -> Self {
pub fn new(full_scan_threshold: Option<usize>, on_disk: Option<bool>) -> Self {
SparseIndexConfig {
full_scan_threshold,
on_disk,

View File

@@ -21,7 +21,7 @@ use crate::index::sparse_index::sparse_search_telemetry::SparseSearchesTelemetry
use crate::index::struct_payload_index::StructPayloadIndex;
use crate::index::{PayloadIndex, VectorIndex};
use crate::telemetry::VectorIndexSearchesTelemetry;
use crate::types::{Filter, SearchParams};
use crate::types::{Filter, SearchParams, DEFAULT_SPARSE_FULL_SCAN_THRESHOLD};
use crate::vector_storage::sparse_raw_scorer::sparse_check_vector;
use crate::vector_storage::{new_stoppable_raw_scorer, VectorStorage, VectorStorageEnum};
@@ -198,7 +198,12 @@ impl<TInvertedIndex: InvertedIndex> VectorIndex for SparseVectorIndex<TInvertedI
);
// if cardinality is small - use plain search
if query_cardinality.max < self.config.full_scan_threshold {
if query_cardinality.max
< self
.config
.full_scan_threshold
.unwrap_or(DEFAULT_SPARSE_FULL_SCAN_THRESHOLD)
{
let _timer =
ScopeDurationMeasurer::new(&self.searches_telemetry.small_cardinality);
return self.search_plain(vectors, filter, top, is_stopped);

View File

@@ -718,6 +718,8 @@ impl VectorDataConfig {
/// Default value based on <https://github.com/google-research/google-research/blob/master/scann/docs/algorithms.md>
pub const DEFAULT_FULL_SCAN_THRESHOLD: usize = 20_000;
pub const DEFAULT_SPARSE_FULL_SCAN_THRESHOLD: usize = 5_000;
/// Persistable state of segment configuration
#[derive(Debug, Deserialize, Serialize, Clone)]
#[serde(rename_all = "snake_case")]