risingwave_storage/hummock/vector/
mod.rs1use risingwave_hummock_sdk::vector_index::VectorFileInfo;
16
17use crate::hummock::vector::file::{VectorBlock, VectorBlockBuilder, VectorBlockMeta};
18use crate::hummock::vector::monitor::VectorStoreCacheStats;
19use crate::hummock::{HummockResult, SstableStoreRef, VectorBlockHolder};
20use crate::vector::VectorRef;
21use crate::vector::hnsw::VectorAccessor;
22
23pub(crate) mod file;
24pub(crate) mod monitor;
25pub(crate) mod writer;
26
27pub struct VectorBlockAccessor {
28 block: VectorBlockHolder,
29 idx: usize,
30}
31
32impl VectorAccessor for VectorBlockAccessor {
33 fn vec_ref(&self) -> VectorRef<'_> {
34 self.block.vec_ref(self.idx)
35 }
36
37 fn info(&self) -> &[u8] {
38 self.block.info(self.idx)
39 }
40}
41
42pub enum EnumVectorAccessor<'a> {
43 Builder(&'a VectorBlockBuilder, usize),
44 BlockRef(&'a VectorBlock, usize),
45 BlockHolder(VectorBlockAccessor),
46}
47
48impl VectorAccessor for EnumVectorAccessor<'_> {
49 fn vec_ref(&self) -> VectorRef<'_> {
50 match self {
51 EnumVectorAccessor::Builder(builder, offset) => builder.vec_ref(*offset),
52 EnumVectorAccessor::BlockRef(block, offset) => block.vec_ref(*offset),
53 EnumVectorAccessor::BlockHolder(accessor) => accessor.vec_ref(),
54 }
55 }
56
57 fn info(&self) -> &[u8] {
58 match self {
59 EnumVectorAccessor::Builder(builder, offset) => builder.info(*offset),
60 EnumVectorAccessor::BlockRef(block, offset) => block.info(*offset),
61 EnumVectorAccessor::BlockHolder(accessor) => accessor.info(),
62 }
63 }
64}
65
66pub async fn get_vector_block(
67 sstable_store: &SstableStoreRef,
68 files: &[VectorFileInfo],
69 idx: usize,
70 stats: &mut VectorStoreCacheStats,
71) -> HummockResult<VectorBlockAccessor> {
72 let vector_file = search_vector_files(files, idx);
73 let meta = sstable_store
74 .get_vector_file_meta(vector_file, stats)
75 .await?;
76 let (block_meta, block_idx, offset) = search_blocks(&meta.block_metas, idx);
77 let block = sstable_store
78 .get_vector_block(vector_file, block_idx, block_meta, stats)
79 .await?;
80 Ok(VectorBlockAccessor { block, idx: offset })
81}
82
83fn search_vector_files(files: &[VectorFileInfo], idx: usize) -> &VectorFileInfo {
84 let (file_idx, _) = search_vector(files, idx, |file| file.start_vector_id);
85 &files[file_idx]
86}
87
88fn search_blocks(blocks: &[VectorBlockMeta], idx: usize) -> (&VectorBlockMeta, usize, usize) {
89 let (block_idx, offset) = search_vector(blocks, idx, |block| block.start_vector_id);
90 (&blocks[block_idx], block_idx, offset)
91}
92
93pub fn search_vector<T>(
95 vector_holders: &[T],
96 idx: usize,
97 get_start_vector_id: impl Fn(&T) -> usize,
98) -> (usize, usize) {
99 let holder_idx = vector_holders
100 .partition_point(|holder| get_start_vector_id(holder) <= idx)
101 .checked_sub(1)
102 .unwrap_or_else(|| {
103 panic!(
104 "idx {} too small for first vector id {}",
105 idx,
106 vector_holders.first().map_or(0, &get_start_vector_id)
107 )
108 });
109 let holder = &vector_holders[holder_idx];
110 let offset = idx - get_start_vector_id(holder);
111 (holder_idx, offset)
112}