Skip to content

Commit

Permalink
[1+2/n][gql-performance][pg] Update tx lookup tables-related schema f…
Browse files Browse the repository at this point in the history
…iles for pg-backed indexer per transactions benchmark findings (#18231)

Apply findings from latest transactions benchmarking. Instead of keeping
indexes on `transactions`, we offload all filtering work to the lookup
tables. Additionally, we add `tx_calls_pkg` and `tx_calls_mod` and
dedicate `tx_calls_fun` to solely handle filters on `package`, `package`
and `module`, and `package`, `module`, and `func` respectively. This is
because it's possible to invoke the same package, mod, and even func in
a transaction.

Finally, the new setup drops `cp_sequence_number` from the lookup tables
and adds `sender` to them to support `sender` + specialized filter. The
Rust structs and code to index data to the lookup tables are also
updated.

The full stack of changes are listed below, but each can stand
independently, and will be individually merged into
`idx-breaking-change-park`
1. #18224 - handling tables
partitioned on epoch's worth of tx_sequence_number
2. #18244 - storing a mapping of
checkpoint -> tx_sequence_number range

---

Check each box that your changes affect. If none of the boxes relate to
your changes, release notes aren't required.

For each box you select, include information after the relevant heading
that describes the impact of your changes that a user might notice and
any actions they must take to implement updates.

- [ ] Protocol:
- [ ] Nodes (Validators and Full nodes):
- [ ] Indexer:
- [ ] JSON-RPC:
- [ ] GraphQL:
- [ ] CLI:
- [ ] Rust SDK:
  • Loading branch information
wlmyng authored and emmazzz committed Jun 20, 2024
1 parent 917272e commit 18ca96b
Show file tree
Hide file tree
Showing 11 changed files with 295 additions and 103 deletions.
20 changes: 9 additions & 11 deletions crates/sui-graphql-rpc/src/types/transaction_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ use async_graphql::{
dataloader::Loader,
*,
};
use diesel::{BoolExpressionMethods, ExpressionMethods, JoinOnDsl, QueryDsl, SelectableHelper};
use diesel::{ExpressionMethods, JoinOnDsl, QueryDsl, SelectableHelper};
use fastcrypto::encoding::{Base58, Encoding};
use serde::{Deserialize, Serialize};
use sui_indexer::{
models::transactions::StoredTransaction,
schema::{
transactions, tx_calls, tx_changed_objects, tx_digests, tx_input_objects, tx_recipients,
tx_senders,
transactions, tx_calls_fun, tx_changed_objects, tx_digests, tx_input_objects,
tx_recipients, tx_senders,
},
};
use sui_types::{
Expand Down Expand Up @@ -317,15 +317,15 @@ impl TransactionBlock {
let mut query = tx::dsl::transactions.into_boxed();

if let Some(f) = &filter.function {
let sub_query = tx_calls::dsl::tx_calls
.select(tx_calls::dsl::tx_sequence_number)
let sub_query = tx_calls_fun::dsl::tx_calls_fun
.select(tx_calls_fun::dsl::tx_sequence_number)
.into_boxed();

query = query.filter(tx::dsl::tx_sequence_number.eq_any(f.apply(
sub_query,
tx_calls::dsl::package,
tx_calls::dsl::module,
tx_calls::dsl::func,
tx_calls_fun::dsl::package,
tx_calls_fun::dsl::module,
tx_calls_fun::dsl::func,
)));
}

Expand Down Expand Up @@ -504,9 +504,7 @@ impl Loader<DigestKey> for Db {
let transactions: Vec<StoredTransaction> = self
.execute(move |conn| {
conn.results(move || {
let join = ds::cp_sequence_number
.eq(tx::checkpoint_sequence_number)
.and(ds::tx_sequence_number.eq(tx::tx_sequence_number));
let join = ds::tx_sequence_number.eq(tx::tx_sequence_number);

tx::transactions
.inner_join(ds::tx_digests.on(join))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
-- This file should undo anything in `up.sql`
DROP TABLE IF EXISTS transactions;
DROP TABLE IF EXISTS transactions_partition_0;
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,3 @@ CREATE TABLE transactions (
PRIMARY KEY (tx_sequence_number, checkpoint_sequence_number)
) PARTITION BY RANGE (checkpoint_sequence_number);
CREATE TABLE transactions_partition_0 PARTITION OF transactions FOR VALUES FROM (0) TO (MAXVALUE);
CREATE INDEX transactions_transaction_digest ON transactions (transaction_digest);
CREATE INDEX transactions_checkpoint_sequence_number ON transactions (checkpoint_sequence_number);
-- only create index for system transactions (0). See types.rs
CREATE INDEX transactions_transaction_kind ON transactions (transaction_kind) WHERE transaction_kind = 0;
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,8 @@ DROP TABLE IF EXISTS tx_senders;
DROP TABLE IF EXISTS tx_recipients;
DROP TABLE IF EXISTS tx_input_objects;
DROP TABLE IF EXISTS tx_changed_objects;
DROP TABLE IF EXISTS tx_calls;
DROP TABLE IF EXISTS tx_calls_pkg;
DROP TABLE IF EXISTS tx_calls_mod;
DROP TABLE IF EXISTS tx_calls_fun;
DROP TABLE IF EXISTS tx_digests;
DROP TABLE IF EXISTS tx_kinds;
Original file line number Diff line number Diff line change
@@ -1,54 +1,67 @@
CREATE TABLE tx_senders (
cp_sequence_number BIGINT NOT NULL,
tx_sequence_number BIGINT NOT NULL,
-- SuiAddress in bytes.
sender BYTEA NOT NULL,
PRIMARY KEY(sender, tx_sequence_number, cp_sequence_number)
PRIMARY KEY(sender, tx_sequence_number)
);
CREATE INDEX tx_senders_tx_sequence_number_index ON tx_senders (tx_sequence_number, cp_sequence_number);

CREATE TABLE tx_recipients (
cp_sequence_number BIGINT NOT NULL,
tx_sequence_number BIGINT NOT NULL,
-- SuiAddress in bytes.
recipient BYTEA NOT NULL,
PRIMARY KEY(recipient, tx_sequence_number, cp_sequence_number)
sender BYTEA NOT NULL,
PRIMARY KEY(recipient, tx_sequence_number)
);
CREATE INDEX tx_recipients_tx_sequence_number_index ON tx_recipients (tx_sequence_number, cp_sequence_number);
CREATE INDEX tx_recipients_sender ON tx_recipients (sender, recipient, tx_sequence_number);

CREATE TABLE tx_input_objects (
cp_sequence_number BIGINT NOT NULL,
tx_sequence_number BIGINT NOT NULL,
-- Object ID in bytes.
object_id BYTEA NOT NULL,
PRIMARY KEY(object_id, tx_sequence_number, cp_sequence_number)
sender BYTEA NOT NULL,
PRIMARY KEY(object_id, tx_sequence_number)
);
CREATE INDEX tx_input_objects_sender ON tx_input_objects (sender, object_id, tx_sequence_number);

CREATE TABLE tx_changed_objects (
cp_sequence_number BIGINT NOT NULL,
tx_sequence_number BIGINT NOT NULL,
-- Object Id in bytes.
object_id BYTEA NOT NULL,
PRIMARY KEY(object_id, tx_sequence_number, cp_sequence_number)
sender BYTEA NOT NULL,
PRIMARY KEY(object_id, tx_sequence_number)
);
CREATE INDEX tx_changed_objects_sender ON tx_changed_objects (sender, object_id, tx_sequence_number);

CREATE TABLE tx_calls_pkg (
tx_sequence_number BIGINT NOT NULL,
package BYTEA NOT NULL,
sender BYTEA NOT NULL,
PRIMARY KEY(package, tx_sequence_number)
);
CREATE INDEX tx_calls_pkg_sender ON tx_calls_pkg (sender, package, tx_sequence_number);

CREATE TABLE tx_calls_mod (
tx_sequence_number BIGINT NOT NULL,
package BYTEA NOT NULL,
module TEXT NOT NULL,
sender BYTEA NOT NULL,
PRIMARY KEY(package, module, tx_sequence_number)
);
CREATE INDEX tx_calls_mod_sender ON tx_calls_mod (sender, package, module, tx_sequence_number);

CREATE TABLE tx_calls (
cp_sequence_number BIGINT NOT NULL,
CREATE TABLE tx_calls_fun (
tx_sequence_number BIGINT NOT NULL,
package BYTEA NOT NULL,
module TEXT NOT NULL,
func TEXT NOT NULL,
-- 1. Using Primary Key as a unique index.
-- 2. Diesel does not like tables with no primary key.
PRIMARY KEY(package, module, func, tx_sequence_number, cp_sequence_number)
sender BYTEA NOT NULL,
PRIMARY KEY(package, module, func, tx_sequence_number)
);
CREATE INDEX tx_calls_package ON tx_calls (package, tx_sequence_number, cp_sequence_number);
CREATE INDEX tx_calls_module ON tx_calls (package, module, tx_sequence_number, cp_sequence_number);
CREATE INDEX tx_calls_tx_sequence_number ON tx_calls (tx_sequence_number, cp_sequence_number);
CREATE INDEX tx_calls_fun_sender ON tx_calls_fun (sender, package, module, func, tx_sequence_number);

-- un-partitioned table for tx_digest -> (cp_sequence_number, tx_sequence_number) lookup.
CREATE TABLE tx_digests (
tx_digest BYTEA PRIMARY KEY,
cp_sequence_number BIGINT NOT NULL,
tx_sequence_number BIGINT NOT NULL
);

CREATE TABLE tx_kinds (
tx_sequence_number BIGINT NOT NULL,
tx_kind SMALLINT NOT NULL,
PRIMARY KEY(tx_kind, tx_sequence_number)
);
9 changes: 5 additions & 4 deletions crates/sui-indexer/src/handlers/checkpoint_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ where
object_changes,
balance_change,
events,
transaction_kind,
transaction_kind: transaction_kind.clone(),
successful_tx_num: if fx.status().is_ok() {
tx.kind().tx_count() as u64
} else {
Expand Down Expand Up @@ -468,8 +468,8 @@ where
// Payers
let payers = vec![tx.gas_owner()];

// Senders
let senders = vec![tx.sender()];
// Sender
let sender = tx.sender();

// Recipients
let recipients = fx
Expand All @@ -495,10 +495,11 @@ where
checkpoint_sequence_number: *checkpoint_seq,
input_objects,
changed_objects,
senders,
sender,
payers,
recipients,
move_calls,
tx_kind: transaction_kind,
});
}
Ok((db_transactions, db_events, db_indices, db_displays))
Expand Down
Loading

0 comments on commit 18ca96b

Please sign in to comment.