From 25cfdda7137d02b58f2ddd62a451145af4084866 Mon Sep 17 00:00:00 2001 From: Jonathan Chappelow Date: Sat, 24 Apr 2021 21:12:41 -0500 Subject: [PATCH] temp index on addresses.tx_vin_vout_row_id for stake invalidation --- db/dcrpg/indexing.go | 2 +- db/dcrpg/internal/addrstmts.go | 2 ++ db/dcrpg/internal/indexes.go | 2 +- db/dcrpg/pgblockchain.go | 4 ++++ db/dcrpg/sync.go | 20 +++++++++++++++++++- 5 files changed, 27 insertions(+), 3 deletions(-) diff --git a/db/dcrpg/indexing.go b/db/dcrpg/indexing.go index a89d9d12f..69dcbba44 100644 --- a/db/dcrpg/indexing.go +++ b/db/dcrpg/indexing.go @@ -556,7 +556,7 @@ func (pgb *ChainDB) IndexAll(barLoad chan *dbtypes.ProgressBarLoad) error { // IndexAddressTable to create them all. {Msg: "addresses table on tx hash", IndexFunc: IndexAddressTableOnTxHash}, {Msg: "addresses table on block time", IndexFunc: IndexBlockTimeOnTableAddress}, - {Msg: "addresses table on address", IndexFunc: IndexAddressTableOnAddress}, + {Msg: "addresses table on address", IndexFunc: IndexAddressTableOnAddress}, // TODO: remove or redefine this or IndexAddressTableOnVoutID since that includes address too {Msg: "addresses table on vout DB ID", IndexFunc: IndexAddressTableOnVoutID}, //{Msg: "addresses table on matching tx hash", IndexFunc: IndexAddressTableOnMatchingTxHash}, diff --git a/db/dcrpg/internal/addrstmts.go b/db/dcrpg/internal/addrstmts.go index a08415b6b..d0735e990 100644 --- a/db/dcrpg/internal/addrstmts.go +++ b/db/dcrpg/internal/addrstmts.go @@ -67,6 +67,8 @@ const ( ` ON addresses(matching_tx_hash);` DeindexAddressTableOnMatchingTxHash = `DROP INDEX IF EXISTS ` + IndexOfAddressTableOnMatchingTx + ` CASCADE;` + // TODO: figure out why this index exists since it's covered by the unique + // on tx_vin_vout_row_id too. IndexAddressTableOnAddress = `CREATE INDEX IF NOT EXISTS ` + IndexOfAddressTableOnAddress + ` ON addresses(address);` DeindexAddressTableOnAddress = `DROP INDEX IF EXISTS ` + IndexOfAddressTableOnAddress + ` CASCADE;` diff --git a/db/dcrpg/internal/indexes.go b/db/dcrpg/internal/indexes.go index 3b9c1a85a..bd25622a2 100644 --- a/db/dcrpg/internal/indexes.go +++ b/db/dcrpg/internal/indexes.go @@ -88,7 +88,7 @@ var IndexDescriptions = map[string]string{ IndexOfVinsTableOnPrevOut: "vins on previous outpoint", IndexOfVoutsTableOnTxHashInd: "vouts on transaction hash and index", IndexOfVoutsTableOnSpendTxID: "vouts on spend_tx_row_id", - IndexOfAddressTableOnAddress: "addresses table on address", + IndexOfAddressTableOnAddress: "addresses table on address", // TODO: remove if it is redundant with IndexOfAddressTableOnVoutID IndexOfAddressTableOnVoutID: "addresses table on vout row id, address, and is_funding", IndexOfAddressTableOnBlockTime: "addresses table on block time", IndexOfAddressTableOnTx: "addresses table on transaction hash", diff --git a/db/dcrpg/pgblockchain.go b/db/dcrpg/pgblockchain.go index 508c5098d..00bf35d5e 100644 --- a/db/dcrpg/pgblockchain.go +++ b/db/dcrpg/pgblockchain.go @@ -3659,6 +3659,10 @@ func (pgb *ChainDB) UpdateLastBlock(msgBlock *wire.MsgBlock, isMainchain bool) e } // Update addresses table for last block's regular transactions. + // So slow without indexes: + // Update on addresses (cost=0.00..1012201.53 rows=1 width=181) + // -> Seq Scan on addresses (cost=0.00..1012201.53 rows=1 width=181) + // Filter: ((NOT is_funding) AND (tx_vin_vout_row_id = 13241234)) err = UpdateLastAddressesValid(pgb.db, lastBlockHash.String(), lastIsValid) if err != nil { return fmt.Errorf("UpdateLastAddressesValid: %v", err) diff --git a/db/dcrpg/sync.go b/db/dcrpg/sync.go index 13d6d9b81..89a696007 100644 --- a/db/dcrpg/sync.go +++ b/db/dcrpg/sync.go @@ -141,6 +141,16 @@ func (pgb *ChainDB) SyncChainDB(ctx context.Context, client rpcutils.MasterBlock return lastBlock, err } + // Create the temporary index on addresses(tx_vin_vout_row_id) that + // prevents the stake disapproval updates to a block to cause massive + // slowdown during initial sync without an index on tx_vin_vout_row_id. + log.Infof("Creating temporary index on addresses(tx_vin_vout_row_id).") + _, err = pgb.db.Exec(`CREATE INDEX IF NOT EXISTS idx_addresses_vinvout_id_tmp ` + + `ON addresses(tx_vin_vout_row_id)`) + if err != nil { + return lastBlock, err + } + // Disable duplicate checks on insert queries since the unique indexes // that enforce the constraints will not exist. pgb.EnableDuplicateCheckOnInsert(false) @@ -377,6 +387,13 @@ func (pgb *ChainDB) SyncChainDB(ctx context.Context, client rpcutils.MasterBlock // Index and analyze tables. var analyzed bool if reindexing { + // drop the temporary index on addresses(tx_vin_vout_row_id). + log.Infof("Dropping temporary index on addresses(tx_vin_vout_row_id).") + _, err = pgb.db.Exec(`DROP INDEX IF EXISTS idx_addresses_vinvout_id_tmp;`) + if err != nil { + return nodeHeight, err + } + // To build indexes, there must NOT be duplicate rows in terms of the // constraints defined by the unique indexes. Duplicate transactions, // vins, and vouts can end up in the tables when identical transactions @@ -388,7 +405,8 @@ func (pgb *ChainDB) SyncChainDB(ctx context.Context, client rpcutils.MasterBlock return 0, err } - // Create all indexes except addresses and tickets indexes. + // Create all indexes except those on addresses.matching_tx_hash, + // vouts.spend_tx_row_id, and all tickets indexes. if err = pgb.IndexAll(barLoad); err != nil { return nodeHeight, fmt.Errorf("IndexAll failed: %v", err) }