Add timestamp to pools table

To speed up historical price queries, add timestamp to pools.
This denormalizes the database a bit for improved query performance.
This commit is contained in:
Dagur Valberg Johannsson 2024-10-08 17:21:22 +02:00
parent fdf03bc48c
commit 3abbdbc177
No known key found for this signature in database
GPG key ID: FD701804AEE88107
3 changed files with 50 additions and 17 deletions

View file

@ -29,7 +29,9 @@ pub fn create_table(conn: &Connection) {
utxo TEXT PRIMARY KEY REFERENCES utxo_funding(new_utxo_hash) ON DELETE CASCADE,
pool TEXT REFERENCES pool(creation_utxo) ON DELETE CASCADE,
txid TEXT REFERENCES tx(txid) ON DELETE CASCADE,
tx_pos TEXT NOT NULL
tx_pos TEXT NOT NULL,
mtp_timestamp BIGINT,
first_seen_timestamp BIGINT
)",
[],
)
@ -83,10 +85,18 @@ fn insert_pool_history_entry(
conn: &Connection,
pool: &OutPointHash,
cauldron: &ParsedContract,
mtp_timestamp: Option<u64>,
first_seen_timestamp: Option<u64>,
) -> Result<()> {
// or replace, as it could have been added in mempool, then block
conn.execute(
"INSERT OR REPLACE INTO pool_history_entry (utxo, pool, txid, tx_pos) VALUES (?, ?, ?, ?)",
"INSERT INTO pool_history_entry (utxo, pool, txid, tx_pos, mtp_timestamp, first_seen_timestamp)
VALUES (?, ?, ?, ?, ?, ?)
ON CONFLICT(utxo) DO UPDATE SET
pool = excluded.pool,
txid = excluded.txid,
tx_pos = excluded.tx_pos,
mtp_timestamp = COALESCE(excluded.mtp_timestamp, pool_history_entry.mtp_timestamp),
first_seen_timestamp = COALESCE(excluded.first_seen_timestamp, pool_history_entry.first_seen_timestamp)",
params![
cauldron
.new_utxo_hash
@ -100,13 +110,20 @@ fn insert_pool_history_entry(
cauldron
.new_utxo_n
.expect("utxo index of new pool history entry"),
mtp_timestamp,
first_seen_timestamp,
],
)
.context("inserting pool_history_entry")?;
Ok(())
}
pub fn update_pool_history(conn: &Connection, cauldrons: Vec<ParsedContract>) -> Result<()> {
pub fn update_pool_history(
conn: &Connection,
cauldrons: Vec<ParsedContract>,
mtp_timestamp: Option<u64>,
first_seen_timestamp: Option<u64>,
) -> Result<()> {
if cauldrons.is_empty() {
return Ok(());
}
@ -158,10 +175,22 @@ pub fn update_pool_history(conn: &Connection, cauldrons: Vec<ParsedContract>) ->
.to_hex()
);
insert_new_pool(conn, &current)?;
insert_pool_history_entry(conn, &pool_utxo, &current)?;
insert_pool_history_entry(
conn,
&pool_utxo,
&current,
mtp_timestamp,
first_seen_timestamp,
)?;
} else {
debug!("New entry for pool {}", pool_utxo.to_hex());
insert_pool_history_entry(conn, &pool_utxo, &current)?;
insert_pool_history_entry(
conn,
&pool_utxo,
&current,
mtp_timestamp,
first_seen_timestamp,
)?;
}
}

View file

@ -2,7 +2,6 @@
//
// This software is licensed under the GNU Affero General Public License (AGPL), version 3.0 or later.
// A copy of the license can be found in the LICENSE file or at https://www.gnu.org/licenses/agpl-3.0.html
use std::time::{SystemTime, UNIX_EPOCH};
use anyhow::Result;
use bitcoin_hashes::hex::{FromHex, ToHex};
@ -35,18 +34,17 @@ pub fn insert_block_tx(
Ok(())
}
pub fn insert_mempool_tx(conn: &rusqlite::Connection, txid: &Txid) -> Result<()> {
pub fn insert_mempool_tx(
conn: &rusqlite::Connection,
txid: &Txid,
first_seen_timestamp: u64,
) -> Result<()> {
let sql = "INSERT INTO tx (txid, first_seen_timestamp)
VALUES (?1, ?2)
ON CONFLICT(txid) DO UPDATE SET
first_seen_timestamp = excluded.first_seen_timestamp";
let current_timestamp = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs() as i64;
conn.execute(sql, params![&txid.to_hex(), current_timestamp])?;
conn.execute(sql, params![&txid.to_hex(), first_seen_timestamp])?;
Ok(())
}

View file

@ -6,6 +6,7 @@
use std::{
collections::HashSet,
sync::{mpsc::sync_channel, Arc, Mutex},
time::{SystemTime, UNIX_EPOCH},
};
use bitcoin_hashes::hex::{FromHex, ToHex};
@ -74,10 +75,15 @@ pub fn update_mempool(db: DBPool, electrum: Arc<Mutex<Client>>) -> Result<()> {
db::cauldron::mempool::delete_mempool_tx(&db_tx, txid)?;
}
let current_timestamp = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs();
for tx in txs_to_add {
let txid = tx.txid();
debug!("mempool add {}", txid.to_hex());
db::cauldron::tx::insert_mempool_tx(&db_tx, &txid)?;
db::cauldron::tx::insert_mempool_tx(&db_tx, &txid, current_timestamp)?;
let cauldrons: Vec<ParsedContract> = tx
.input
.iter()
@ -92,7 +98,7 @@ pub fn update_mempool(db: DBPool, electrum: Arc<Mutex<Client>>) -> Result<()> {
all_cauldrons.extend(cauldrons);
}
db::cauldron::pool::update_pool_history(&db_tx, all_cauldrons)
db::cauldron::pool::update_pool_history(&db_tx, all_cauldrons, None, Some(current_timestamp))
.context("update pool history")?;
Ok(db_tx.commit()?)
@ -236,7 +242,7 @@ pub fn index_blocks(
}
// Figuring out initial utxo needs to be done on all cauldrons in a block.
db::cauldron::pool::update_pool_history(&db_tx, all_cauldrons)
db::cauldron::pool::update_pool_history(&db_tx, all_cauldrons, Some(mtp), None)
.context("update pool history")?;
config_set(&db_tx, KEY_LAST_INDEXED, &blockhash.to_hex());