Skip to content

Commit fd1d09a

Browse files
fix(cubestore): don't add all measures to default preagg index (#8789)
* fix(cubestore): don't add all measures to default preagg index * add tests * Update docs --------- Co-authored-by: Igor Lukanin <[email protected]>
1 parent 6b17731 commit fd1d09a

File tree

2 files changed

+112
-5
lines changed

2 files changed

+112
-5
lines changed

docs/pages/product/caching/using-pre-aggregations.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ monitor Cube Store workers load, and iterate as needed.
286286

287287
**When you define a pre-aggregation without any explicit indexes, the default
288288
index is created.** In this index, dimensions come first, time dimensions come
289-
second, and measures come last.
289+
second.
290290

291291
When you define additional indexes, you don't incur any additional costs on
292292
the data warehouse side. However, the pre-aggregation build time for a

rust/cubestore/cubestore/src/metastore/mod.rs

Lines changed: 111 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2134,7 +2134,7 @@ impl MetaStore for RocksMetaStore {
21342134
} else {
21352135
None
21362136
};
2137-
let aggregate_column_indices = if let Some(aggrs) = aggregates {
2137+
let aggregate_column_indices = if let Some(ref aggrs) = aggregates {
21382138
let res = aggrs.iter()
21392139
.map(|aggr| {
21402140
let aggr_column = &aggr.1;
@@ -2232,6 +2232,14 @@ impl MetaStore for RocksMetaStore {
22322232
index_def,
22332233
)?;
22342234
}
2235+
2236+
let aggr_column_names = if let Some(ref aggrs) = aggregates {
2237+
aggrs.iter()
2238+
.map(|aggr| aggr.1.clone())
2239+
.collect::<Vec<String>>()
2240+
} else {
2241+
vec![]
2242+
};
22352243
let def_index_columns = table_id
22362244
.get_row()
22372245
.unique_key_columns()
@@ -2242,9 +2250,10 @@ impl MetaStore for RocksMetaStore {
22422250
ColumnType::Bytes => None,
22432251
ColumnType::HyperLogLog(_) => None,
22442252
_ => {
2245-
if seq_column_index.is_none()
2246-
|| seq_column_index.is_some()
2247-
&& c.get_index() as u64 != seq_column_index.unwrap()
2253+
if !aggr_column_names.contains(&c.get_name())
2254+
&& seq_column_index.is_none()
2255+
|| (seq_column_index.is_some()
2256+
&& c.get_index() as u64 != seq_column_index.unwrap())
22482257
{
22492258
Some(c.get_name().clone())
22502259
} else {
@@ -5640,6 +5649,104 @@ mod tests {
56405649
let _ = fs::remove_dir_all(remote_store_path.clone());
56415650
}
56425651

5652+
#[tokio::test]
5653+
async fn table_with_default_index_no_measures_test() {
5654+
init_test_logger().await;
5655+
5656+
let config = Config::test("table_with_default_index_no_measures_test");
5657+
let store_path = env::current_dir()
5658+
.unwrap()
5659+
.join("test-table-default-index-no-measure-local");
5660+
let remote_store_path = env::current_dir()
5661+
.unwrap()
5662+
.join("test-table-default-index-no-measure-remote");
5663+
let _ = fs::remove_dir_all(store_path.clone());
5664+
let _ = fs::remove_dir_all(remote_store_path.clone());
5665+
let remote_fs = LocalDirRemoteFs::new(Some(remote_store_path.clone()), store_path.clone());
5666+
{
5667+
let meta_store = RocksMetaStore::new(
5668+
store_path.clone().join("metastore").as_path(),
5669+
BaseRocksStoreFs::new_for_metastore(remote_fs.clone(), config.config_obj()),
5670+
config.config_obj(),
5671+
)
5672+
.unwrap();
5673+
5674+
meta_store
5675+
.create_schema("foo".to_string(), false)
5676+
.await
5677+
.unwrap();
5678+
let mut columns = Vec::new();
5679+
columns.push(Column::new("col1".to_string(), ColumnType::Int, 0));
5680+
columns.push(Column::new("col2".to_string(), ColumnType::String, 1));
5681+
columns.push(Column::new("col3".to_string(), ColumnType::Int, 2));
5682+
columns.push(Column::new("aggr_col1".to_string(), ColumnType::Int, 3));
5683+
columns.push(Column::new("aggr_col2".to_string(), ColumnType::String, 4));
5684+
columns.push(Column::new("aggr_col3".to_string(), ColumnType::Int, 5));
5685+
5686+
let table1 = meta_store
5687+
.create_table(
5688+
"foo".to_string(),
5689+
"boo".to_string(),
5690+
columns.clone(),
5691+
None,
5692+
None,
5693+
vec![],
5694+
true,
5695+
None,
5696+
None,
5697+
None,
5698+
None,
5699+
None,
5700+
None,
5701+
Some(vec![
5702+
("sum".to_string(), "aggr_col1".to_string()),
5703+
("max".to_string(), "aggr_col2".to_string()),
5704+
("min".to_string(), "aggr_col3".to_string()),
5705+
]),
5706+
None,
5707+
None,
5708+
false,
5709+
None,
5710+
)
5711+
.await
5712+
.unwrap();
5713+
5714+
let table_id = table1.get_id();
5715+
5716+
assert_eq!(
5717+
meta_store
5718+
.get_table("foo".to_string(), "boo".to_string())
5719+
.await
5720+
.unwrap(),
5721+
table1
5722+
);
5723+
5724+
let indexes = meta_store.get_table_indexes(table_id).await.unwrap();
5725+
assert_eq!(indexes.len(), 1);
5726+
let ind = &indexes[0];
5727+
5728+
let index = ind.get_row();
5729+
assert_eq!(index.get_name(), &"default".to_string());
5730+
assert!(match index.get_type() {
5731+
IndexType::Regular => true,
5732+
_ => false,
5733+
});
5734+
assert_eq!(index.sort_key_size(), 3); // The main test point is here, sort key should exclude all measures
5735+
5736+
let expected_columns = vec![
5737+
Column::new("col1".to_string(), ColumnType::Int, 0),
5738+
Column::new("col2".to_string(), ColumnType::String, 1),
5739+
Column::new("col3".to_string(), ColumnType::Int, 2),
5740+
Column::new("aggr_col1".to_string(), ColumnType::Int, 3),
5741+
Column::new("aggr_col2".to_string(), ColumnType::String, 4),
5742+
Column::new("aggr_col3".to_string(), ColumnType::Int, 5),
5743+
];
5744+
assert_eq!(index.get_columns(), &expected_columns);
5745+
}
5746+
let _ = fs::remove_dir_all(store_path.clone());
5747+
let _ = fs::remove_dir_all(remote_store_path.clone());
5748+
}
5749+
56435750
#[tokio::test]
56445751
async fn cold_start_test() {
56455752
init_test_logger().await;

0 commit comments

Comments
 (0)