@@ -17,6 +17,8 @@ use databend_common_io::constants::DEFAULT_BLOCK_COMPRESSED_SIZE;
1717use databend_common_io:: constants:: DEFAULT_BLOCK_PER_SEGMENT ;
1818use databend_common_io:: constants:: DEFAULT_BLOCK_ROW_COUNT ;
1919
20+ const MAX_BYTES_PER_BLOCK_FACTOR : usize = 2 ;
21+
2022#[ derive( Clone , Copy , Debug , serde:: Serialize , serde:: Deserialize ) ]
2123pub struct BlockThresholds {
2224 pub max_rows_per_block : usize ,
@@ -35,11 +37,11 @@ impl Default for BlockThresholds {
3537 fn default ( ) -> BlockThresholds {
3638 BlockThresholds {
3739 max_rows_per_block : DEFAULT_BLOCK_ROW_COUNT ,
38- min_rows_per_block : ( DEFAULT_BLOCK_ROW_COUNT * 4 ) . div_ceil ( 5 ) ,
39- max_bytes_per_block : DEFAULT_BLOCK_BUFFER_SIZE * 2 ,
40- min_bytes_per_block : ( DEFAULT_BLOCK_BUFFER_SIZE * 4 ) . div_ceil ( 5 ) ,
40+ min_rows_per_block : Self :: min_block_threshold ( DEFAULT_BLOCK_ROW_COUNT ) ,
41+ max_bytes_per_block : DEFAULT_BLOCK_BUFFER_SIZE * MAX_BYTES_PER_BLOCK_FACTOR ,
42+ min_bytes_per_block : Self :: min_block_threshold ( DEFAULT_BLOCK_BUFFER_SIZE ) ,
4143 max_compressed_per_block : DEFAULT_BLOCK_COMPRESSED_SIZE ,
42- min_compressed_per_block : ( DEFAULT_BLOCK_COMPRESSED_SIZE * 4 ) . div_ceil ( 5 ) ,
44+ min_compressed_per_block : Self :: min_block_threshold ( DEFAULT_BLOCK_COMPRESSED_SIZE ) ,
4345 block_per_segment : DEFAULT_BLOCK_PER_SEGMENT ,
4446 }
4547 }
@@ -54,15 +56,34 @@ impl BlockThresholds {
5456 ) -> Self {
5557 BlockThresholds {
5658 max_rows_per_block,
57- min_rows_per_block : ( max_rows_per_block * 4 ) . div_ceil ( 5 ) ,
58- max_bytes_per_block : bytes_per_block * 2 ,
59- min_bytes_per_block : ( bytes_per_block * 4 ) . div_ceil ( 5 ) ,
59+ min_rows_per_block : Self :: min_block_threshold ( max_rows_per_block) ,
60+ max_bytes_per_block : bytes_per_block * MAX_BYTES_PER_BLOCK_FACTOR ,
61+ min_bytes_per_block : Self :: min_block_threshold ( bytes_per_block) ,
6062 max_compressed_per_block,
61- min_compressed_per_block : ( max_compressed_per_block * 4 ) . div_ceil ( 5 ) ,
63+ min_compressed_per_block : Self :: min_block_threshold ( max_compressed_per_block) ,
6264 block_per_segment,
6365 }
6466 }
6567
68+ #[ inline]
69+ pub fn set_rows_per_block ( mut self , rows_per_block : usize ) -> Self {
70+ self . max_rows_per_block = rows_per_block;
71+ self . min_rows_per_block = Self :: min_block_threshold ( rows_per_block) ;
72+ self
73+ }
74+
75+ #[ inline]
76+ pub fn set_bytes_per_block ( mut self , bytes_per_block : usize ) -> Self {
77+ self . max_bytes_per_block = bytes_per_block * MAX_BYTES_PER_BLOCK_FACTOR ;
78+ self . min_bytes_per_block = Self :: min_block_threshold ( bytes_per_block) ;
79+ self
80+ }
81+
82+ #[ inline]
83+ pub fn min_block_threshold ( value : usize ) -> usize {
84+ ( value * 4 ) . div_ceil ( 5 )
85+ }
86+
6687 #[ inline]
6788 pub fn check_perfect_block (
6889 & self ,
@@ -112,63 +133,80 @@ impl BlockThresholds {
112133 }
113134
114135 #[ inline]
115- pub fn calc_rows_for_compact ( & self , total_bytes : usize , total_rows : usize ) -> usize {
116- if self . check_for_compact ( total_rows, total_bytes) {
117- return total_rows;
118- }
136+ pub fn calc_compact_block_num ( & self , total_rows : usize , total_bytes : usize ) -> usize {
137+ let block_num_by_rows = if total_rows >= 2 * self . min_rows_per_block {
138+ ( total_rows / self . max_rows_per_block ) . max ( 2 )
139+ } else {
140+ 1
141+ } ;
119142
120- let block_num_by_rows = std:: cmp:: max ( total_rows / self . min_rows_per_block , 1 ) ;
121- let block_num_by_size = total_bytes / self . min_bytes_per_block ;
122- if block_num_by_rows >= block_num_by_size {
123- return self . max_rows_per_block ;
124- }
125- total_rows. div_ceil ( block_num_by_size)
143+ let bytes_per_block = self . max_bytes_per_block / MAX_BYTES_PER_BLOCK_FACTOR ;
144+ let block_num_by_bytes = if total_bytes >= 2 * self . min_bytes_per_block {
145+ ( total_bytes / bytes_per_block) . max ( 2 )
146+ } else {
147+ 1
148+ } ;
149+
150+ block_num_by_rows. max ( block_num_by_bytes) . min ( total_rows)
126151 }
127152
128- /// Calculates the optimal number of rows per block based on total data size and row count.
153+ /// Calculates the optimal rows and bytes per block based on total data size and row count.
129154 ///
130155 /// # Parameters
131156 /// - `total_bytes`: The total size of the data in bytes.
132157 /// - `total_rows`: The total number of rows in the data.
133158 /// - `total_compressed`: The total compressed size of the data in bytes.
134159 ///
135160 /// # Returns
136- /// - The calculated number of rows per block that satisfies the thresholds.
161+ /// - `(rows_per_block, bytes_per_block)`: rows are used as the sort block size,
162+ /// and bytes are used by ordered compact to keep post-sort blocks near the
163+ /// recluster target.
137164 #[ inline]
138165 pub fn calc_rows_for_recluster (
139166 & self ,
140167 total_rows : usize ,
141168 total_bytes : usize ,
142169 total_compressed : usize ,
143- ) -> usize {
170+ ) -> ( usize , usize ) {
171+ debug_assert ! ( total_rows > 0 ) ;
172+
173+ let default_bytes_per_block = self
174+ . max_bytes_per_block
175+ . div_ceil ( MAX_BYTES_PER_BLOCK_FACTOR ) ;
144176 // Check if the data is compact enough to skip further calculations.
145177 if self . check_for_compact ( total_rows, total_bytes)
146178 && total_compressed < 2 * self . min_compressed_per_block
147179 {
148- return total_rows;
180+ return ( total_rows, default_bytes_per_block ) ;
149181 }
150182
151183 let block_num_by_rows = std:: cmp:: max ( total_rows / self . min_rows_per_block , 1 ) ;
152184 let block_num_by_compressed = total_compressed. div_ceil ( self . max_compressed_per_block ) ;
153185 // If row-based block count exceeds compressed-based block count, use max rows per block.
154186 if block_num_by_rows >= block_num_by_compressed {
155- return self . max_rows_per_block ;
187+ return ( self . max_rows_per_block , default_bytes_per_block ) ;
156188 }
157189
158190 let bytes_per_block = total_bytes. div_ceil ( block_num_by_compressed) ;
159191 // Adjust the number of blocks based on block size thresholds.
160- let max_bytes_per_block = self . max_bytes_per_block . min ( 400 * 1024 * 1024 ) ;
161- let min_bytes_per_block = ( self . min_bytes_per_block / 2 ) . min ( 50 * 1024 * 1024 ) ;
162- let block_nums = if bytes_per_block > max_bytes_per_block {
192+ let max_bytes_per_block =
193+ default_bytes_per_block + default_bytes_per_block . min ( DEFAULT_BLOCK_BUFFER_SIZE ) ;
194+ if bytes_per_block > max_bytes_per_block {
163195 // Case 1: If the block size is too bigger.
164- total_bytes. div_ceil ( max_bytes_per_block)
165- } else if bytes_per_block < min_bytes_per_block {
196+ let bytes_per_block = max_bytes_per_block;
197+ let block_nums = total_bytes. div_ceil ( bytes_per_block) ;
198+ ( total_rows. div_ceil ( block_nums) . max ( 1 ) , bytes_per_block)
199+ } else if bytes_per_block < self . min_bytes_per_block {
166200 // Case 2: If the block size is too smaller.
167- total_bytes / min_bytes_per_block
201+ let bytes_per_block = self . min_bytes_per_block ;
202+ let block_nums = std:: cmp:: max ( total_bytes / bytes_per_block, 1 ) ;
203+ ( total_rows. div_ceil ( block_nums) . max ( 1 ) , bytes_per_block)
168204 } else {
169205 // Case 3: Otherwise, use the compressed-based block count.
170- block_num_by_compressed
171- } ;
172- total_rows. div_ceil ( block_nums. max ( 1 ) ) . max ( 1 )
206+ (
207+ total_rows. div_ceil ( block_num_by_compressed) . max ( 1 ) ,
208+ bytes_per_block,
209+ )
210+ }
173211 }
174212}
0 commit comments