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}