Skip to main content

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