From 73346792952c5538aafc42a2ee778f0069a98607 Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Mon, 29 Jan 2024 20:41:41 +0200 Subject: [PATCH] fix(db): Make `get_expected_l1_batch_timestamp()` more efficient (#963) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hopefully. It's not the exact same query as previously, but it should be equivalent. ## What ❔ Makes `get_expected_l1_batch_timestamp()` DB query more efficient (hopefully) by getting rid of the `WHERE l1_batch_number IS NULL` clause. ## Why ❔ Inefficient DB queries are bad, mkay. ## Checklist - [x] PR title corresponds to the body of PR (we generate changelog entries from PRs). - [x] Code has been formatted via `zk fmt` and `zk lint`. - [x] Spellcheck has been run via `zk spellcheck`. - [x] Linkcheck has been run via `zk linkcheck`. --- ...3fe77e649e9d110043d2ac22005dd61cfcfb9.json | 22 ----- ...c026c3181f42a49f1f4b6e227c95641931a54.json | 22 +++++ ...16f8cc32e365e2ffbd17dc99885de427f2777.json | 22 +++++ core/lib/dal/src/blocks_web3_dal.rs | 86 +++++++++++++------ 4 files changed, 105 insertions(+), 47 deletions(-) delete mode 100644 core/lib/dal/.sqlx/query-3191f5ba16af041123ffa941ad63fe77e649e9d110043d2ac22005dd61cfcfb9.json create mode 100644 core/lib/dal/.sqlx/query-51891ab674b8f5cf2d7c12420d1c026c3181f42a49f1f4b6e227c95641931a54.json create mode 100644 core/lib/dal/.sqlx/query-c8155c4e4701fc771918ac1bb4d16f8cc32e365e2ffbd17dc99885de427f2777.json diff --git a/core/lib/dal/.sqlx/query-3191f5ba16af041123ffa941ad63fe77e649e9d110043d2ac22005dd61cfcfb9.json b/core/lib/dal/.sqlx/query-3191f5ba16af041123ffa941ad63fe77e649e9d110043d2ac22005dd61cfcfb9.json deleted file mode 100644 index 4290ba1f1b3..00000000000 --- a/core/lib/dal/.sqlx/query-3191f5ba16af041123ffa941ad63fe77e649e9d110043d2ac22005dd61cfcfb9.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n SELECT\n timestamp\n FROM\n miniblocks\n WHERE\n (\n $1::BIGINT IS NULL\n AND l1_batch_number IS NULL\n )\n OR (l1_batch_number = $1::BIGINT)\n ORDER BY\n number\n LIMIT\n 1\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "timestamp", - "type_info": "Int8" - } - ], - "parameters": { - "Left": [ - "Int8" - ] - }, - "nullable": [ - false - ] - }, - "hash": "3191f5ba16af041123ffa941ad63fe77e649e9d110043d2ac22005dd61cfcfb9" -} diff --git a/core/lib/dal/.sqlx/query-51891ab674b8f5cf2d7c12420d1c026c3181f42a49f1f4b6e227c95641931a54.json b/core/lib/dal/.sqlx/query-51891ab674b8f5cf2d7c12420d1c026c3181f42a49f1f4b6e227c95641931a54.json new file mode 100644 index 00000000000..ed13428a569 --- /dev/null +++ b/core/lib/dal/.sqlx/query-51891ab674b8f5cf2d7c12420d1c026c3181f42a49f1f4b6e227c95641931a54.json @@ -0,0 +1,22 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT\n timestamp\n FROM\n miniblocks\n WHERE\n number = COALESCE(\n (\n SELECT\n MAX(number) + 1\n FROM\n miniblocks\n WHERE\n l1_batch_number = $1\n ),\n (\n SELECT\n MAX(miniblock_number) + 1\n FROM\n snapshot_recovery\n WHERE\n l1_batch_number = $1\n )\n )\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "timestamp", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false + ] + }, + "hash": "51891ab674b8f5cf2d7c12420d1c026c3181f42a49f1f4b6e227c95641931a54" +} diff --git a/core/lib/dal/.sqlx/query-c8155c4e4701fc771918ac1bb4d16f8cc32e365e2ffbd17dc99885de427f2777.json b/core/lib/dal/.sqlx/query-c8155c4e4701fc771918ac1bb4d16f8cc32e365e2ffbd17dc99885de427f2777.json new file mode 100644 index 00000000000..78582f6242b --- /dev/null +++ b/core/lib/dal/.sqlx/query-c8155c4e4701fc771918ac1bb4d16f8cc32e365e2ffbd17dc99885de427f2777.json @@ -0,0 +1,22 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT\n timestamp\n FROM\n miniblocks\n WHERE\n l1_batch_number = $1\n ORDER BY\n number\n LIMIT\n 1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "timestamp", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false + ] + }, + "hash": "c8155c4e4701fc771918ac1bb4d16f8cc32e365e2ffbd17dc99885de427f2777" +} diff --git a/core/lib/dal/src/blocks_web3_dal.rs b/core/lib/dal/src/blocks_web3_dal.rs index 0a44ebcf9be..f9afb2b5828 100644 --- a/core/lib/dal/src/blocks_web3_dal.rs +++ b/core/lib/dal/src/blocks_web3_dal.rs @@ -258,31 +258,67 @@ impl BlocksWeb3Dal<'_, '_> { &mut self, l1_batch_number: &ResolvedL1BatchForMiniblock, ) -> sqlx::Result> { - let timestamp = sqlx::query!( - r#" - SELECT - timestamp - FROM - miniblocks - WHERE - ( - $1::BIGINT IS NULL - AND l1_batch_number IS NULL - ) - OR (l1_batch_number = $1::BIGINT) - ORDER BY - number - LIMIT - 1 - "#, - l1_batch_number - .miniblock_l1_batch - .map(|number| i64::from(number.0)) - ) - .fetch_optional(self.storage.conn()) - .await? - .map(|row| row.timestamp as u64); - Ok(timestamp) + if let Some(miniblock_l1_batch) = l1_batch_number.miniblock_l1_batch { + Ok(sqlx::query!( + r#" + SELECT + timestamp + FROM + miniblocks + WHERE + l1_batch_number = $1 + ORDER BY + number + LIMIT + 1 + "#, + i64::from(miniblock_l1_batch.0) + ) + .fetch_optional(self.storage.conn()) + .await? + .map(|row| row.timestamp as u64)) + } else { + // Got a pending miniblock. Searching the timestamp of the first pending miniblock using + // `WHERE l1_batch_number IS NULL` is slow since it potentially locks the `miniblocks` table. + // Instead, we determine its number using the previous L1 batch, taking into the account that + // it may be stored in the `snapshot_recovery` table. + let prev_l1_batch_number = if l1_batch_number.pending_l1_batch == L1BatchNumber(0) { + return Ok(None); // We haven't created the genesis miniblock yet + } else { + l1_batch_number.pending_l1_batch - 1 + }; + Ok(sqlx::query!( + r#" + SELECT + timestamp + FROM + miniblocks + WHERE + number = COALESCE( + ( + SELECT + MAX(number) + 1 + FROM + miniblocks + WHERE + l1_batch_number = $1 + ), + ( + SELECT + MAX(miniblock_number) + 1 + FROM + snapshot_recovery + WHERE + l1_batch_number = $1 + ) + ) + "#, + i64::from(prev_l1_batch_number.0) + ) + .fetch_optional(self.storage.conn()) + .await? + .map(|row| row.timestamp as u64)) + } } pub async fn get_miniblock_hash(