qdrant_client/builders/
optimizers_config_diff_builder.rs

1use crate::qdrant::*;
2
3#[derive(Clone)]
4pub struct OptimizersConfigDiffBuilder {
5    ///
6    /// The minimal fraction of deleted vectors in a segment, required to perform segment optimization
7    pub(crate) deleted_threshold: Option<Option<f64>>,
8    ///
9    /// The minimal number of vectors in a segment, required to perform segment optimization
10    pub(crate) vacuum_min_vector_number: Option<Option<u64>>,
11    ///
12    /// Target amount of segments the optimizer will try to keep.
13    /// Real amount of segments may vary depending on multiple parameters:
14    ///
15    /// - Amount of stored points.
16    /// - Current write RPS.
17    ///
18    /// It is recommended to select the default number of segments as a factor of the number of search threads,
19    /// so that each segment would be handled evenly by one of the threads.
20    pub(crate) default_segment_number: Option<Option<u64>>,
21    ///
22    /// Do not create segments larger this size (in kilobytes).
23    /// Large segments might require disproportionately long indexation times,
24    /// therefore it makes sense to limit the size of segments.
25    ///
26    /// If indexing speed is more important - make this parameter lower.
27    /// If search speed is more important - make this parameter higher.
28    /// Note: 1Kb = 1 vector of size 256
29    /// If not set, will be automatically selected considering the number of available CPUs.
30    pub(crate) max_segment_size: Option<Option<u64>>,
31    ///
32    /// Maximum size (in kilobytes) of vectors to store in-memory per segment.
33    /// Segments larger than this threshold will be stored as read-only memmaped file.
34    ///
35    /// Memmap storage is disabled by default, to enable it, set this threshold to a reasonable value.
36    ///
37    /// To disable memmap storage, set this to `0`.
38    ///
39    /// Note: 1Kb = 1 vector of size 256
40    pub(crate) memmap_threshold: Option<Option<u64>>,
41    ///
42    /// Maximum size (in kilobytes) of vectors allowed for plain index, exceeding this threshold will enable vector indexing
43    ///
44    /// Default value is 20,000, based on <<https://github.com/google-research/google-research/blob/master/scann/docs/algorithms.md>.>
45    ///
46    /// To disable vector indexing, set to `0`.
47    ///
48    /// Note: 1kB = 1 vector of size 256.
49    pub(crate) indexing_threshold: Option<Option<u64>>,
50    ///
51    /// Interval between forced flushes.
52    pub(crate) flush_interval_sec: Option<Option<u64>>,
53    ///
54    /// Max number of threads (jobs) for running optimizations per shard.
55    /// Each optimization job will also use `max_indexing_threads` threads by itself for index building.
56    ///
57    /// - If `auto` - have no limit and choose dynamically to saturate CPU.
58    /// - If `disabled` or `0` - no optimization threads, optimizations will be disabled.
59    pub(crate) max_optimization_threads: Option<Option<MaxOptimizationThreads>>,
60}
61
62impl OptimizersConfigDiffBuilder {
63    ///
64    /// The minimal fraction of deleted vectors in a segment, required to perform segment optimization
65    pub fn deleted_threshold(self, value: f64) -> Self {
66        let mut new = self;
67        new.deleted_threshold = Option::Some(Option::Some(value));
68        new
69    }
70    ///
71    /// The minimal number of vectors in a segment, required to perform segment optimization
72    pub fn vacuum_min_vector_number(self, value: u64) -> Self {
73        let mut new = self;
74        new.vacuum_min_vector_number = Option::Some(Option::Some(value));
75        new
76    }
77    ///
78    /// Target amount of segments the optimizer will try to keep.
79    /// Real amount of segments may vary depending on multiple parameters:
80    ///
81    /// - Amount of stored points.
82    /// - Current write RPS.
83    ///
84    /// It is recommended to select the default number of segments as a factor of the number of search threads,
85    /// so that each segment would be handled evenly by one of the threads.
86    pub fn default_segment_number(self, value: u64) -> Self {
87        let mut new = self;
88        new.default_segment_number = Option::Some(Option::Some(value));
89        new
90    }
91    ///
92    /// Do not create segments larger this size (in kilobytes).
93    /// Large segments might require disproportionately long indexation times,
94    /// therefore it makes sense to limit the size of segments.
95    ///
96    /// If indexing speed is more important - make this parameter lower.
97    /// If search speed is more important - make this parameter higher.
98    /// Note: 1Kb = 1 vector of size 256
99    /// If not set, will be automatically selected considering the number of available CPUs.
100    pub fn max_segment_size(self, value: u64) -> Self {
101        let mut new = self;
102        new.max_segment_size = Option::Some(Option::Some(value));
103        new
104    }
105    ///
106    /// Maximum size (in kilobytes) of vectors to store in-memory per segment.
107    /// Segments larger than this threshold will be stored as read-only memmaped file.
108    ///
109    /// Memmap storage is disabled by default, to enable it, set this threshold to a reasonable value.
110    ///
111    /// To disable memmap storage, set this to `0`.
112    ///
113    /// Note: 1Kb = 1 vector of size 256
114    pub fn memmap_threshold(self, value: u64) -> Self {
115        let mut new = self;
116        new.memmap_threshold = Option::Some(Option::Some(value));
117        new
118    }
119    ///
120    /// Maximum size (in kilobytes) of vectors allowed for plain index, exceeding this threshold will enable vector indexing
121    ///
122    /// Default value is 20,000, based on <<https://github.com/google-research/google-research/blob/master/scann/docs/algorithms.md>.>
123    ///
124    /// To disable vector indexing, set to `0`.
125    ///
126    /// Note: 1kB = 1 vector of size 256.
127    pub fn indexing_threshold(self, value: u64) -> Self {
128        let mut new = self;
129        new.indexing_threshold = Option::Some(Option::Some(value));
130        new
131    }
132    ///
133    /// Interval between forced flushes.
134    pub fn flush_interval_sec(self, value: u64) -> Self {
135        let mut new = self;
136        new.flush_interval_sec = Option::Some(Option::Some(value));
137        new
138    }
139    ///
140    /// Max number of threads (jobs) for running optimizations per shard.
141    /// Each optimization job will also use `max_indexing_threads` threads by itself for index building.
142    ///
143    /// - If `auto` - have no limit and choose dynamically to saturate CPU.
144    /// - If `disabled` or `0` - no optimization threads, optimizations will be disabled.
145    ///
146    /// ```no_run
147    ///# use qdrant_client::{Qdrant, QdrantError};
148    /// use qdrant_client::qdrant::{OptimizersConfigDiffBuilder, UpdateCollectionBuilder, MaxOptimizationThreadsBuilder};
149    ///
150    ///# async fn create_collection(client: &Qdrant)
151    ///# -> Result<(), QdrantError> {
152    /// let optimizers_config = OptimizersConfigDiffBuilder::default()
153    ///     // Use exactly 8 threads
154    ///     .max_optimization_threads(8)
155    ///     // Or automatically choose
156    ///     .max_optimization_threads(MaxOptimizationThreadsBuilder::auto())
157    ///     // Or disable
158    ///     .max_optimization_threads(MaxOptimizationThreadsBuilder::disabled());
159    ///
160    /// client
161    ///     .update_collection(
162    ///         UpdateCollectionBuilder::new("my_collection").optimizers_config(optimizers_config),
163    ///     )
164    ///     .await?;
165    ///# Ok(())
166    ///# }
167    /// ```
168    pub fn max_optimization_threads<VALUE: Into<MaxOptimizationThreads>>(
169        self,
170        value: VALUE,
171    ) -> Self {
172        let mut new = self;
173        new.max_optimization_threads = Option::Some(Option::Some(value.into()));
174        new
175    }
176
177    fn build_inner(self) -> Result<OptimizersConfigDiff, std::convert::Infallible> {
178        Ok(OptimizersConfigDiff {
179            deleted_threshold: self.deleted_threshold.unwrap_or_default(),
180            vacuum_min_vector_number: self.vacuum_min_vector_number.unwrap_or_default(),
181            default_segment_number: self.default_segment_number.unwrap_or_default(),
182            max_segment_size: self.max_segment_size.unwrap_or_default(),
183            memmap_threshold: self.memmap_threshold.unwrap_or_default(),
184            indexing_threshold: self.indexing_threshold.unwrap_or_default(),
185            flush_interval_sec: self.flush_interval_sec.unwrap_or_default(),
186            max_optimization_threads: self.max_optimization_threads.unwrap_or_default(),
187            // Deprecated: replaced with max_optimization_threads
188            deprecated_max_optimization_threads: None,
189        })
190    }
191    /// Create an empty builder, with all fields set to `None` or `PhantomData`.
192    fn create_empty() -> Self {
193        Self {
194            deleted_threshold: core::default::Default::default(),
195            vacuum_min_vector_number: core::default::Default::default(),
196            default_segment_number: core::default::Default::default(),
197            max_segment_size: core::default::Default::default(),
198            memmap_threshold: core::default::Default::default(),
199            indexing_threshold: core::default::Default::default(),
200            flush_interval_sec: core::default::Default::default(),
201            max_optimization_threads: core::default::Default::default(),
202        }
203    }
204}
205
206impl From<OptimizersConfigDiffBuilder> for OptimizersConfigDiff {
207    fn from(value: OptimizersConfigDiffBuilder) -> Self {
208        value.build_inner().unwrap_or_else(|_| {
209            panic!(
210                "Failed to convert {0} to {1}",
211                "OptimizersConfigDiffBuilder", "OptimizersConfigDiff"
212            )
213        })
214    }
215}
216
217impl OptimizersConfigDiffBuilder {
218    /// Builds the desired type. Can often be omitted.
219    pub fn build(self) -> OptimizersConfigDiff {
220        self.build_inner().unwrap_or_else(|_| {
221            panic!(
222                "Failed to build {0} into {1}",
223                "OptimizersConfigDiffBuilder", "OptimizersConfigDiff"
224            )
225        })
226    }
227}
228
229impl Default for OptimizersConfigDiffBuilder {
230    fn default() -> Self {
231        Self::create_empty()
232    }
233}