Skip to content

Commit 1b6e50b

Browse files
committed
cleanup and optimise database
1 parent bdf367c commit 1b6e50b

24 files changed

+274
-632
lines changed

crates/database/db/src/db.rs

Lines changed: 12 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -862,7 +862,7 @@ mod test {
862862
BatchCommitData, BatchInfo, BlockInfo, L1MessageEnvelope, L2BlockInfoWithL1Messages,
863863
};
864864
use scroll_alloy_consensus::TxL1Message;
865-
use sea_orm::{ColumnTrait, EntityTrait, QueryFilter};
865+
use sea_orm::EntityTrait;
866866

867867
#[tokio::test]
868868
async fn test_database_round_trip_batch_commit() {
@@ -1227,11 +1227,13 @@ mod test {
12271227

12281228
#[tokio::test]
12291229
async fn test_delete_l1_messages_gt() {
1230+
reth_tracing::init_test_tracing();
1231+
12301232
// Set up the test database.
12311233
let db = setup_test_db().await;
12321234

12331235
// Generate unstructured bytes.
1234-
let mut bytes = [0u8; 1024];
1236+
let mut bytes = [0u8; 10240];
12351237
rand::rng().fill(bytes.as_mut_slice());
12361238
let mut u = Unstructured::new(&bytes);
12371239

@@ -1276,9 +1278,13 @@ mod test {
12761278

12771279
#[tokio::test]
12781280
async fn test_get_l2_block_info_by_number() {
1281+
reth_tracing::init_test_tracing();
1282+
12791283
// Set up the test database.
12801284
let db = setup_test_db().await;
12811285

1286+
println!("im here");
1287+
12821288
// Generate unstructured bytes.
12831289
let mut bytes = [0u8; 1024];
12841290
rand::rng().fill(bytes.as_mut_slice());
@@ -1289,6 +1295,8 @@ mod test {
12891295
let batch_info: BatchInfo = batch_data.clone().into();
12901296
db.insert_batch(batch_data).await.unwrap();
12911297

1298+
println!("inserted batch");
1299+
12921300
// Generate and insert multiple L2 blocks
12931301
let mut block_infos = Vec::new();
12941302
for i in 200..205 {
@@ -1297,6 +1305,8 @@ mod test {
12971305
}
12981306
db.insert_blocks(block_infos.clone(), batch_info).await.unwrap();
12991307

1308+
println!("inserted blocks");
1309+
13001310
// Test getting existing blocks
13011311
for expected_block in block_infos {
13021312
let retrieved_block =
@@ -1475,67 +1485,6 @@ mod test {
14751485
}
14761486
}
14771487

1478-
#[tokio::test]
1479-
async fn test_insert_block_upsert_behavior() {
1480-
reth_tracing::init_test_tracing();
1481-
1482-
// Set up the test database.
1483-
let db = setup_test_db().await;
1484-
1485-
// Generate unstructured bytes.
1486-
let mut bytes = [0u8; 1024];
1487-
rand::rng().fill(bytes.as_mut_slice());
1488-
let mut u = Unstructured::new(&bytes);
1489-
1490-
// Generate batches
1491-
let batch_data_1 = BatchCommitData { index: 100, ..Arbitrary::arbitrary(&mut u).unwrap() };
1492-
let batch_info_1: BatchInfo = batch_data_1.clone().into();
1493-
let batch_data_2 = BatchCommitData { index: 200, ..Arbitrary::arbitrary(&mut u).unwrap() };
1494-
let batch_info_2: BatchInfo = batch_data_2.clone().into();
1495-
1496-
db.insert_batch(batch_data_1).await.unwrap();
1497-
db.insert_batch(batch_data_2).await.unwrap();
1498-
1499-
// Insert initial block
1500-
let block_info = BlockInfo { number: 600, hash: B256::arbitrary(&mut u).unwrap() };
1501-
db.insert_blocks(vec![block_info], batch_info_1).await.unwrap();
1502-
1503-
// Verify initial insertion
1504-
let retrieved_block = db.get_l2_block_info_by_number(600).await.unwrap();
1505-
assert_eq!(retrieved_block, Some(block_info));
1506-
1507-
// Verify initial batch association using model conversion
1508-
let initial_l2_block_model = models::l2_block::Entity::find()
1509-
.filter(models::l2_block::Column::BlockNumber.eq(600))
1510-
.one(db.inner().get_connection())
1511-
.await
1512-
.unwrap()
1513-
.unwrap();
1514-
let (initial_block_info, initial_batch_info): (BlockInfo, BatchInfo) =
1515-
initial_l2_block_model.into();
1516-
assert_eq!(initial_block_info, block_info);
1517-
assert_eq!(initial_batch_info, batch_info_1);
1518-
1519-
// Update the same block with different batch info (upsert)
1520-
db.insert_blocks(vec![block_info], batch_info_2).await.unwrap();
1521-
1522-
// Verify the block still exists and was updated
1523-
let retrieved_block = db.get_l2_block_info_by_number(600).await.unwrap().unwrap();
1524-
assert_eq!(retrieved_block, block_info);
1525-
1526-
// Verify batch association was updated using model conversion
1527-
let updated_l2_block_model = models::l2_block::Entity::find()
1528-
.filter(models::l2_block::Column::BlockNumber.eq(600))
1529-
.one(db.inner().get_connection())
1530-
.await
1531-
.unwrap()
1532-
.unwrap();
1533-
let (updated_block_info, updated_batch_info): (BlockInfo, BatchInfo) =
1534-
updated_l2_block_model.into();
1535-
assert_eq!(updated_block_info, block_info);
1536-
assert_eq!(updated_batch_info, batch_info_2);
1537-
}
1538-
15391488
#[tokio::test]
15401489
async fn test_prepare_on_startup() {
15411490
let db = setup_test_db().await;

crates/database/db/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ pub use db::Database;
99
mod error;
1010
pub use error::DatabaseError;
1111

12+
mod maintenance;
13+
pub use maintenance::DatabaseMaintenance;
14+
1215
mod metrics;
1316

1417
mod models;
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
use sea_orm::ConnectionTrait;
2+
3+
use crate::DatabaseConnectionProvider;
4+
5+
use super::Database;
6+
use std::sync::Arc;
7+
8+
/// The interval in seconds between optimization runs in seconds.
9+
const PERIODIC_MAINTENANCE_INTERVAL_SECS: u64 = 600;
10+
11+
/// Provides maintenance operations for the database.
12+
#[derive(Debug)]
13+
pub struct DatabaseMaintenance {
14+
db: Arc<Database>,
15+
}
16+
17+
impl DatabaseMaintenance {
18+
/// Creates a new `DatabaseMaintenance` instance.
19+
pub const fn new(db: Arc<Database>) -> Self {
20+
Self { db }
21+
}
22+
23+
/// Runs the maintenance tasks in a loop.
24+
pub async fn run(self) {
25+
self.startup_maintenance().await;
26+
27+
loop {
28+
tokio::time::sleep(std::time::Duration::from_secs(PERIODIC_MAINTENANCE_INTERVAL_SECS))
29+
.await;
30+
self.periodic_maintenance().await;
31+
}
32+
}
33+
34+
/// Runs maintenance tasks at startup.
35+
///
36+
/// This includes running `ANALYZE` and `PRAGMA optimize`.
37+
async fn startup_maintenance(&self) {
38+
let db = self.db.inner();
39+
let conn = db.get_connection();
40+
41+
tracing::info!(target: "scroll::db::maintenance", "running startup ANALYZE...");
42+
if let Err(err) = conn.execute_unprepared("ANALYZE;").await {
43+
tracing::warn!(target: "scroll::db::maintenance", "ANALYZE failed: {:?}", err);
44+
}
45+
46+
tracing::info!(target: "scroll::db::maintenance", "running PRAGMA optimize at startup...");
47+
if let Err(err) = conn.execute_unprepared("PRAGMA optimize;").await {
48+
tracing::warn!(target: "scroll::db::maintenance", "PRAGMA optimize failed: {:?}", err);
49+
}
50+
51+
tracing::info!(target: "scroll::db::maintenance", "startup maintenance complete.");
52+
}
53+
54+
/// Runs periodic maintenance tasks.
55+
///
56+
/// This includes running `PRAGMA optimize`.
57+
async fn periodic_maintenance(&self) {
58+
let db = self.db.inner();
59+
let conn = db.get_connection();
60+
61+
tracing::info!(target: "scroll::db::maintenance", "running periodic PRAGMA optimize...");
62+
if let Err(err) = conn.execute_unprepared("PRAGMA optimize;").await {
63+
tracing::warn!(target: "scroll::db::maintenance", "PRAGMA optimize failed: {:?}", err);
64+
} else {
65+
tracing::info!(target: "scroll::db::maintenance", "periodic PRAGMA optimize complete.");
66+
}
67+
}
68+
}

crates/database/db/src/operations.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -708,13 +708,15 @@ impl<T: WriteConnectionProvider + ?Sized + Sync> DatabaseWriteOperations for T {
708708
blocks.into_iter().map(|b| (b, batch_info).into()).collect();
709709
models::l2_block::Entity::insert_many(l2_blocks)
710710
.on_conflict(
711-
OnConflict::column(models::l2_block::Column::BlockHash)
712-
.update_columns([
713-
models::l2_block::Column::BlockNumber,
714-
models::l2_block::Column::BatchHash,
715-
models::l2_block::Column::BatchIndex,
716-
])
717-
.to_owned(),
711+
OnConflict::columns([
712+
models::l2_block::Column::BlockHash,
713+
models::l2_block::Column::BatchHash,
714+
])
715+
.update_columns([
716+
models::l2_block::Column::BlockNumber,
717+
models::l2_block::Column::BatchIndex,
718+
])
719+
.to_owned(),
718720
)
719721
.on_empty_do_nothing()
720722
.exec_without_returning(self.get_connection())

crates/database/migration/src/lib.rs

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,7 @@ mod m20250408_132123_add_header_metadata;
66
mod m20250408_150338_load_header_metadata;
77
mod m20250411_072004_add_l2_block;
88
mod m20250616_223947_add_metadata;
9-
mod m20250825_093350_remove_unsafe_l2_blocks;
10-
mod m20250829_042803_add_table_indexes;
119
mod m20250904_175949_block_signature;
12-
mod m20250923_135359_add_index_block_hash;
13-
mod m20250929_161536_add_additional_indexes;
14-
mod m20251001_125444_add_index_status;
15-
mod m20251005_160938_add_initial_l1_block_numbers;
16-
mod m20251013_140946_add_initial_l1_processed_block_number;
17-
mod m20251021_070729_add_skipped_column;
18-
mod m20251021_144852_add_queue_index_index;
19-
mod m20251027_090416_add_table_statistics;
2010
mod m20251028_110719_add_l1_block_table;
2111

2212
mod migration_info;
@@ -36,17 +26,7 @@ impl<MI: MigrationInfo + Send + Sync + 'static> MigratorTrait for Migrator<MI> {
3626
Box::new(m20250408_150338_load_header_metadata::Migration::<MI>(Default::default())),
3727
Box::new(m20250411_072004_add_l2_block::Migration::<MI>(Default::default())),
3828
Box::new(m20250616_223947_add_metadata::Migration),
39-
Box::new(m20250825_093350_remove_unsafe_l2_blocks::Migration),
40-
Box::new(m20250829_042803_add_table_indexes::Migration),
4129
Box::new(m20250904_175949_block_signature::Migration),
42-
Box::new(m20250923_135359_add_index_block_hash::Migration),
43-
Box::new(m20250929_161536_add_additional_indexes::Migration),
44-
Box::new(m20251001_125444_add_index_status::Migration),
45-
Box::new(m20251005_160938_add_initial_l1_block_numbers::Migration),
46-
Box::new(m20251013_140946_add_initial_l1_processed_block_number::Migration),
47-
Box::new(m20251021_070729_add_skipped_column::Migration),
48-
Box::new(m20251021_144852_add_queue_index_index::Migration),
49-
Box::new(m20251027_090416_add_table_statistics::Migration),
5030
Box::new(m20251028_110719_add_l1_block_table::Migration),
5131
]
5232
}

crates/database/migration/src/m20220101_000001_create_batch_commit_table.rs

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ impl MigrationTrait for Migration {
1515
Table::create()
1616
.table(BatchCommit::Table)
1717
.if_not_exists()
18-
.col(big_unsigned(BatchCommit::Index))
19-
.col(binary_len(BatchCommit::Hash, HASH_LENGTH).primary_key())
18+
.col(pk_auto(BatchCommit::Id))
19+
.col(big_unsigned(BatchCommit::Index).not_null())
20+
.col(binary_len(BatchCommit::Hash, HASH_LENGTH).not_null().unique_key())
2021
.col(big_unsigned(BatchCommit::BlockNumber))
2122
.col(big_unsigned(BatchCommit::BlockTimestamp))
2223
.col(binary(BatchCommit::Calldata))
@@ -50,6 +51,64 @@ impl MigrationTrait for Migration {
5051
))
5152
.await?;
5253

54+
// Indexes:
55+
// ------------------------------------------------------------
56+
57+
// Add index on "index" column in batch_commit table.
58+
manager
59+
.create_index(
60+
Index::create()
61+
.name("idx_batch_commit_batch_index")
62+
.col(BatchCommit::Index)
63+
.table(BatchCommit::Table)
64+
.to_owned(),
65+
)
66+
.await?;
67+
68+
// Add index on "block number" column in batch_commit table.
69+
manager
70+
.create_index(
71+
Index::create()
72+
.name("idx_batch_commit_block_number")
73+
.col(BatchCommit::BlockNumber)
74+
.table(BatchCommit::Table)
75+
.to_owned(),
76+
)
77+
.await?;
78+
79+
// Add index on "finalized block number" column in batch_commit table.
80+
manager
81+
.create_index(
82+
Index::create()
83+
.name("idx_batch_commit_finalized_block_number")
84+
.col(BatchCommit::FinalizedBlockNumber)
85+
.table(BatchCommit::Table)
86+
.to_owned(),
87+
)
88+
.await?;
89+
90+
// Add index on "reverted block number" column in batch_commit table.
91+
manager
92+
.create_index(
93+
Index::create()
94+
.name("idx_batch_commit_reverted_block_number")
95+
.col(BatchCommit::RevertedBlockNumber)
96+
.table(BatchCommit::Table)
97+
.to_owned(),
98+
)
99+
.await?;
100+
101+
// Add index on `status` for the `batch_commit` table.
102+
manager
103+
.create_index(
104+
Index::create()
105+
.name("idx_batch_commit_status")
106+
.col(BatchCommit::Status)
107+
.table(BatchCommit::Table)
108+
.to_owned(),
109+
)
110+
.await?;
111+
53112
Ok(())
54113
}
55114

@@ -61,6 +120,7 @@ impl MigrationTrait for Migration {
61120
#[derive(DeriveIden)]
62121
pub(crate) enum BatchCommit {
63122
Table,
123+
Id,
64124
Index,
65125
Hash,
66126
BlockNumber,

0 commit comments

Comments
 (0)