Skip to content

Commit

Permalink
Fix index removal and additions + add smoketest (#1444)
Browse files Browse the repository at this point in the history
  • Loading branch information
Centril committed Jun 19, 2024
1 parent 137f26d commit a93bd49
Show file tree
Hide file tree
Showing 7 changed files with 289 additions and 156 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,22 @@ impl CommittedState {
Ok(())
}

/// After replaying all old transactions,
/// inserts and deletes into the system tables
/// might not be reflected in the schemas of the built tables.
/// So we must re-schema every built table.
pub(super) fn reschema_tables(&mut self) -> Result<()> {
// For already built tables, we need to reschema them to account for constraints et al.
let mut schemas = Vec::with_capacity(self.tables.len());
for table_id in self.tables.keys().copied() {
schemas.push(self.schema_for_table_raw(&ExecutionContext::default(), table_id)?);
}
for (table, schema) in self.tables.values_mut().zip(schemas) {
table.with_mut_schema(|s| *s = schema);
}
Ok(())
}

/// After replaying all old transactions, tables which have rows will
/// have been created in memory, but tables with no rows will not have
/// been created. This function ensures that they are created.
Expand Down
18 changes: 11 additions & 7 deletions crates/core/src/db/datastore/locking_tx_datastore/datastore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ impl Locking {
// `build_missing_tables` must be called before indexes.
// Honestly this should maybe just be one big procedure.
// See John Carmack's philosophy on this.
committed_state.reschema_tables()?;
committed_state.build_missing_tables()?;
committed_state.build_indexes()?;
committed_state.build_sequence_state(&mut sequence_state)?;
Expand Down Expand Up @@ -390,7 +391,7 @@ impl MutTxDatastore for Locking {
}

fn drop_index_mut_tx(&self, tx: &mut Self::MutTx, index_id: IndexId) -> Result<()> {
tx.drop_index(index_id, self.database_address)
tx.drop_index(index_id, true, self.database_address)
}

fn index_id_from_name_mut_tx(&self, tx: &Self::MutTx, index_name: &str) -> Result<Option<IndexId>> {
Expand All @@ -414,11 +415,13 @@ impl MutTxDatastore for Locking {
}

fn drop_constraint_mut_tx(&self, tx: &mut Self::MutTx, constraint_id: ConstraintId) -> Result<()> {
tx.drop_constraint(constraint_id, self.database_address)
let ctx = &ExecutionContext::internal(self.database_address);
tx.drop_constraint(ctx, constraint_id)
}

fn constraint_id_from_name(&self, tx: &Self::MutTx, constraint_name: &str) -> Result<Option<ConstraintId>> {
tx.constraint_id_from_name(constraint_name, self.database_address)
let ctx = &ExecutionContext::internal(self.database_address);
tx.constraint_id_from_name(ctx, constraint_name)
}

fn iter_mut_tx<'a>(
Expand Down Expand Up @@ -1254,8 +1257,8 @@ mod tests {
IdxSchema { id: seq_start + 1, table, col: 1, name: "name_idx", unique: true },
]),
map_array([
ConstraintRow { constraint_id: seq_start, table_id: table, columns: col(0), constraints: Constraints::unique(), constraint_name: "ct_Foo_id_idx_unique" },
ConstraintRow { constraint_id: seq_start + 1, table_id: table, columns: col(1), constraints: Constraints::unique(), constraint_name: "ct_Foo_name_idx_unique" }
ConstraintRow { constraint_id: seq_start, table_id: table, columns: col(0), constraints: Constraints::unique(), constraint_name: "ct_Foo_id_unique" },
ConstraintRow { constraint_id: seq_start + 1, table_id: table, columns: col(1), constraints: Constraints::unique(), constraint_name: "ct_Foo_name_unique" }
]),
map_array([
SequenceRow { id: seq_start, table, col_pos: 0, name: "seq_Foo_id", start: 1 }
Expand Down Expand Up @@ -1747,16 +1750,17 @@ mod tests {
fn test_create_index_pre_commit() -> ResultTest<()> {
let (datastore, tx, table_id) = setup_table()?;
datastore.commit_mut_tx_for_test(tx)?;

let mut tx = datastore.begin_mut_tx(IsolationLevel::Serializable);
let row = u32_str_u32(0, "Foo", 18); // 0 will be ignored.
datastore.insert_mut_tx(&mut tx, table_id, row)?;
datastore.commit_mut_tx_for_test(tx)?;

let mut tx = datastore.begin_mut_tx(IsolationLevel::Serializable);
let index_def = IndexDef::btree("age_idx".into(), ColId(2), true);
datastore.create_index_mut_tx(&mut tx, table_id, index_def)?;
let ctx = ExecutionContext::default();
let query = query_st_tables(&ctx, &tx);

let seq_start = FIRST_NON_SYSTEM_ID;
let index_rows = query.scan_st_indexes()?;
#[rustfmt::skip]
Expand All @@ -1782,7 +1786,7 @@ mod tests {
cols: _,
value: _,
}))) => (),
_ => panic!("Expected an unique constraint violation error."),
e => panic!("Expected an unique constraint violation error but got {e:?}."),
}
#[rustfmt::skip]
assert_eq!(all_rows(&datastore, &tx, table_id), vec![u32_str_u32(1, "Foo", 18)]);
Expand Down
Loading

3 comments on commit a93bd49

@github-actions
Copy link

@github-actions github-actions bot commented on a93bd49 Jun 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmarking failed. Please check the workflow run for details.

@github-actions
Copy link

@github-actions github-actions bot commented on a93bd49 Jun 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bot test failed. Please check the workflow run for details.

@github-actions
Copy link

@github-actions github-actions bot commented on a93bd49 Jun 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Callgrind benchmark results

Callgrind Benchmark Report

These benchmarks were run using callgrind,
an instruction-level profiler. They allow comparisons between sqlite (sqlite), SpacetimeDB running through a module (stdb_module), and the underlying SpacetimeDB data storage engine (stdb_raw). Callgrind emulates a CPU to collect the below estimates.

Measurement changes larger than five percent are in bold.

In-memory benchmarks

callgrind: empty transaction

db total reads + writes old total reads + writes Δrw estimated cycles old estimated cycles Δcycles
stdb_raw 5139 5138 0.02% 5207 5176 0.60%
sqlite 5518 5528 -0.18% 5968 6026 -0.96%

callgrind: filter

db schema indices count preload _column data_type total reads + writes old total reads + writes Δrw estimated cycles old estimated cycles Δcycles
stdb_raw u32_u64_str no_index 64 128 1 u64 77842 77841 0.00% 78264 78297 -0.04%
stdb_raw u32_u64_str no_index 64 128 2 string 120512 120511 0.00% 121182 121127 0.05%
stdb_raw u32_u64_str btree_each_column 64 128 1 u64 23073 23072 0.00% 23391 23484 -0.40%
stdb_raw u32_u64_str btree_each_column 64 128 2 string 24111 24113 -0.01% 24505 24601 -0.39%
sqlite u32_u64_str no_index 64 128 2 string 143491 143491 0.00% 145095 145113 -0.01%
sqlite u32_u64_str no_index 64 128 1 u64 122848 122842 0.00% 124202 124246 -0.04%
sqlite u32_u64_str btree_each_column 64 128 2 string 133290 133290 0.00% 135030 134940 0.07%
sqlite u32_u64_str btree_each_column 64 128 1 u64 130149 130149 0.00% 131681 131639 0.03%

callgrind: insert bulk

db schema indices count preload total reads + writes old total reads + writes Δrw estimated cycles old estimated cycles Δcycles
stdb_raw u32_u64_str unique_0 64 128 871436 867141 0.50% 894116 886993 0.80%
stdb_raw u32_u64_str btree_each_column 64 128 1010591 1010777 -0.02% 1035855 1042813 -0.67%
sqlite u32_u64_str unique_0 64 128 396139 396139 0.00% 414581 414231 0.08%
sqlite u32_u64_str btree_each_column 64 128 981456 981456 0.00% 1024712 1023028 0.16%

callgrind: iterate

db schema indices count total reads + writes old total reads + writes Δrw estimated cycles old estimated cycles Δcycles
stdb_raw u32_u64_str unique_0 1024 151302 151301 0.00% 151374 151343 0.02%
stdb_raw u32_u64_str unique_0 64 15287 15286 0.01% 15355 15324 0.20%
sqlite u32_u64_str unique_0 1024 1046680 1046690 -0.00% 1050058 1049878 0.02%
sqlite u32_u64_str unique_0 64 74826 74836 -0.01% 75936 75828 0.14%

callgrind: serialize_product_value

count format total reads + writes old total reads + writes Δrw estimated cycles old estimated cycles Δcycles
64 json 47438 47438 0.00% 50056 49988 0.14%
64 bsatn 25716 25716 0.00% 27926 28028 -0.36%
16 bsatn 8117 8117 0.00% 9409 9545 -1.42%
16 json 12142 12142 0.00% 14012 13944 0.49%

callgrind: update bulk

db schema indices count preload total reads + writes old total reads + writes Δrw estimated cycles old estimated cycles Δcycles
stdb_raw u32_u64_str unique_0 1024 1024 20427038 19945570 2.41% 20915660 20424654 2.40%
stdb_raw u32_u64_str unique_0 64 128 1275707 1270860 0.38% 1309793 1306516 0.25%
sqlite u32_u64_str unique_0 1024 1024 1802040 1802040 0.00% 1811318 1811286 0.00%
sqlite u32_u64_str unique_0 64 128 128386 128386 0.00% 131206 131196 0.01%
On-disk benchmarks

callgrind: empty transaction

db total reads + writes old total reads + writes Δrw estimated cycles old estimated cycles Δcycles
stdb_raw 5149 5148 0.02% 5217 5186 0.60%
sqlite 5560 5566 -0.11% 6074 6200 -2.03%

callgrind: filter

db schema indices count preload _column data_type total reads + writes old total reads + writes Δrw estimated cycles old estimated cycles Δcycles
stdb_raw u32_u64_str no_index 64 128 1 u64 77852 77851 0.00% 78246 78303 -0.07%
stdb_raw u32_u64_str no_index 64 128 2 string 120522 120521 0.00% 121112 121097 0.01%
stdb_raw u32_u64_str btree_each_column 64 128 1 u64 23083 23082 0.00% 23401 23490 -0.38%
stdb_raw u32_u64_str btree_each_column 64 128 2 string 24122 24120 0.01% 24516 24604 -0.36%
sqlite u32_u64_str no_index 64 128 2 string 145412 145412 0.00% 147244 147374 -0.09%
sqlite u32_u64_str no_index 64 128 1 u64 124753 124753 0.00% 126329 126483 -0.12%
sqlite u32_u64_str btree_each_column 64 128 2 string 135412 135427 -0.01% 137538 137527 0.01%
sqlite u32_u64_str btree_each_column 64 128 1 u64 132245 132245 0.00% 134035 134201 -0.12%

callgrind: insert bulk

db schema indices count preload total reads + writes old total reads + writes Δrw estimated cycles old estimated cycles Δcycles
stdb_raw u32_u64_str unique_0 64 128 820862 816970 0.48% 843066 867708 -2.84%
stdb_raw u32_u64_str btree_each_column 64 128 958989 955960 0.32% 983859 1017300 -3.29%
sqlite u32_u64_str unique_0 64 128 413676 413676 0.00% 431418 431082 0.08%
sqlite u32_u64_str btree_each_column 64 128 1019717 1019717 0.00% 1062749 1059733 0.28%

callgrind: iterate

db schema indices count total reads + writes old total reads + writes Δrw estimated cycles old estimated cycles Δcycles
stdb_raw u32_u64_str unique_0 1024 151312 151311 0.00% 151380 151345 0.02%
stdb_raw u32_u64_str unique_0 64 15297 15296 0.01% 15365 15334 0.20%
sqlite u32_u64_str unique_0 1024 1049748 1049754 -0.00% 1053470 1053636 -0.02%
sqlite u32_u64_str unique_0 64 76598 76598 0.00% 77916 77906 0.01%

callgrind: serialize_product_value

count format total reads + writes old total reads + writes Δrw estimated cycles old estimated cycles Δcycles
64 json 47438 47438 0.00% 50056 49988 0.14%
64 bsatn 25716 25716 0.00% 27926 28028 -0.36%
16 bsatn 8117 8117 0.00% 9409 9545 -1.42%
16 json 12142 12142 0.00% 14012 13944 0.49%

callgrind: update bulk

db schema indices count preload total reads + writes old total reads + writes Δrw estimated cycles old estimated cycles Δcycles
stdb_raw u32_u64_str unique_0 1024 1024 18964150 18895863 0.36% 19502402 19453953 0.25%
stdb_raw u32_u64_str unique_0 64 128 1232645 1226608 0.49% 1296719 1291974 0.37%
sqlite u32_u64_str unique_0 1024 1024 1809601 1809601 0.00% 1818217 1818257 -0.00%
sqlite u32_u64_str unique_0 64 128 132512 132512 0.00% 135532 135466 0.05%

Please sign in to comment.