From 947c2a61f1616ce5caab0cf0bd019d9fadbe3a93 Mon Sep 17 00:00:00 2001 From: Bartek Nowotarski Date: Wed, 12 Oct 2022 21:39:57 +0100 Subject: [PATCH] services/horizon: Add (asset, account_id) index to trust_lines table (#4635) Adds a new index to `trust_lines` table on `(asset_type, asset_code, asset_issuer, account_id)` fields. When filtering by `asset` in `/accounts` endpoint the underlying query was using `"trust_lines_by_type_code_issuer" btree (asset_type, asset_code, asset_issuer)` index. This can be slow when querying for a popular asset which (like `USDC`) because when selected trust lines are found by a DB engine, they later need to be sorted by account id. A new index allow quick sorting of found trustlines. ### Query plan without a new index ``` Limit (cost=2760.42..2787.18 rows=10 width=249) (actual time=725.657..734.633 rows=10 loops=1) -> Nested Loop (cost=2760.42..7229.44 rows=1670 width=249) (actual time=725.656..734.631 rows=10 loops=1) -> Gather Merge (cost=2759.86..2950.19 rows=1670 width=57) (actual time=725.622..734.541 rows=10 loops=1) Workers Planned: 1 Workers Launched: 1 -> Sort (cost=1759.85..1762.30 rows=982 width=57) (actual time=719.248..719.275 rows=203 loops=2) Sort Key: trust_lines.account_id Sort Method: external merge Disk: 8104kB Worker 0: Sort Method: external merge Disk: 7472kB -> Parallel Bitmap Heap Scan on trust_lines (cost=24.86..1711.05 rows=982 width=57) (actual time=49.144..656.403 rows=118316 loops=2) Recheck Cond: ((asset_type = 1) AND ((asset_code)::text = 'USDC'::text) AND ((asset_issuer)::text = 'GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN'::text)) Rows Removed by Index Recheck: 1905016 Heap Blocks: exact=18001 lossy=87732 -> Bitmap Index Scan on trust_lines_by_type_code_issuer (cost=0.00..24.44 rows=1670 width=0) (actual time=45.137..45.137 rows=236633 loops=1) Index Cond: ((asset_type = 1) AND ((asset_code)::text = 'USDC'::text) AND ((asset_issuer)::text = 'GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN'::text)) -> Index Scan using accounts_pkey on accounts (cost=0.56..2.56 rows=1 width=192) (actual time=0.008..0.008 rows=1 loops=10) Index Cond: ((account_id)::text = (trust_lines.account_id)::text) Planning Time: 2.946 ms Execution Time: 738.166 ms (19 rows) ``` ### Query plan **with** a new index ``` Limit (cost=1.25..27.29 rows=10 width=249) (actual time=0.319..0.376 rows=10 loops=1) -> Nested Loop (cost=1.25..4351.51 rows=1670 width=249) (actual time=0.318..0.374 rows=10 loops=1) -> Index Only Scan using trust_lines_by_account_type_code_issuer on trust_lines (cost=0.69..72.26 rows=1670 width=57) (actual time=0.303..0.308 rows=10 loops=1) Index Cond: ((asset_type = 1) AND (asset_code = 'USDC'::text) AND (asset_issuer = 'GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN'::text)) Heap Fetches: 0 -> Index Scan using accounts_pkey on accounts (cost=0.56..2.56 rows=1 width=192) (actual time=0.006..0.006 rows=1 loops=10) Index Cond: ((account_id)::text = (trust_lines.account_id)::text) Planning Time: 2.113 ms Execution Time: 0.420 ms (9 rows) ``` --- .../horizon/internal/db2/schema/bindata.go | 23 +++++++++++++++++++ ...rust_lines_by_account_type_code_issuer.sql | 9 ++++++++ 2 files changed, 32 insertions(+) create mode 100644 services/horizon/internal/db2/schema/migrations/61_trust_lines_by_account_type_code_issuer.sql diff --git a/services/horizon/internal/db2/schema/bindata.go b/services/horizon/internal/db2/schema/bindata.go index 95485b5732..36b6a2ca6a 100644 --- a/services/horizon/internal/db2/schema/bindata.go +++ b/services/horizon/internal/db2/schema/bindata.go @@ -57,6 +57,7 @@ // migrations/59_remove_foreign_key_constraints.sql (981B) // migrations/5_create_trades_table.sql (1.1kB) // migrations/60_add_asset_id_indexes.sql (289B) +// migrations/61_trust_lines_by_account_type_code_issuer.sql (383B) // migrations/6_create_assets_table.sql (366B) // migrations/7_modify_trades_table.sql (2.303kB) // migrations/8_add_aggregators.sql (907B) @@ -1270,6 +1271,26 @@ func migrations60_add_asset_id_indexesSql() (*asset, error) { return a, nil } +var _migrations61_trust_lines_by_account_type_code_issuerSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xa4\x8f\xcf\xca\x82\x50\x10\x47\xf7\xf3\x14\x83\xab\x4f\x3e\x7d\x82\xbb\x8a\x94\x70\xa3\x61\x09\xed\x06\xff\x0c\x71\xa1\x54\xee\xcc\x25\x7c\xfb\x28\x2b\x5c\x26\xed\xce\x62\xe6\xf0\x3b\x71\x8c\xff\x57\x7b\x76\xb5\x32\x56\x23\xc0\xb6\x4c\x37\xc7\x14\xb3\x3c\x49\x4f\x18\xa8\xf3\xa2\x74\xb1\x3d\x0b\x35\x13\xe9\x34\x32\xb5\x43\xc7\x64\x45\x3c\x3b\xaa\xdb\x76\xf0\xbd\x06\x58\xe4\xb8\xb8\xc5\xea\x90\xe5\x3b\x6c\xd4\x31\xe3\x5f\x2d\xc2\xfa\xfc\x8d\x70\xe6\x87\xe2\xcd\xb3\x29\xc2\x97\x8a\x6c\x17\x1a\x48\xca\x62\xff\xe5\x86\xc0\x00\x2c\x23\x92\xe1\xd6\xc3\x1a\xc1\x27\xc2\xac\x8b\xff\x3d\x3a\x34\x70\x0f\x00\x00\xff\xff\xae\x55\x70\x5f\x7f\x01\x00\x00") + +func migrations61_trust_lines_by_account_type_code_issuerSqlBytes() ([]byte, error) { + return bindataRead( + _migrations61_trust_lines_by_account_type_code_issuerSql, + "migrations/61_trust_lines_by_account_type_code_issuer.sql", + ) +} + +func migrations61_trust_lines_by_account_type_code_issuerSql() (*asset, error) { + bytes, err := migrations61_trust_lines_by_account_type_code_issuerSqlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "migrations/61_trust_lines_by_account_type_code_issuer.sql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x6e, 0xc, 0x3a, 0xa, 0xcd, 0x1f, 0x39, 0x26, 0xd2, 0xd0, 0xe1, 0x22, 0xc3, 0x42, 0x7a, 0x79, 0xd6, 0x32, 0xf3, 0xf0, 0x8e, 0x86, 0x3e, 0xc6, 0xfc, 0x54, 0x3c, 0x40, 0x5a, 0x5e, 0x71, 0x9}} + return a, nil +} + var _migrations6_create_assets_tableSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x6c\x90\x3d\x4f\xc3\x30\x18\x84\x77\xff\x8a\x1b\x1d\x91\x0e\x20\xe8\x92\xc9\x34\x16\x58\x18\xa7\xb8\x31\xa2\x53\xe5\x26\x16\x78\x80\x54\xb6\x11\xca\xbf\x47\xaa\x28\xf9\x50\xe6\x7b\xf4\xbc\xef\xdd\x6a\x85\xab\x4f\xff\x1e\x6c\x72\x30\x27\xb2\xd1\x9c\xd5\x1c\x35\xbb\x97\x1c\x1f\x3e\xa6\x2e\xf4\x07\x1b\xa3\x4b\x11\x94\x00\x80\x6f\xb1\xe3\x5a\x30\x89\xad\x16\xcf\x4c\xef\xf1\xc4\xf7\xc8\xcf\xd9\x19\x3c\xa4\xfe\xe4\xf0\xca\xf4\xe6\x91\x69\xba\xbe\xcd\xa0\xaa\x1a\xca\x48\x39\x86\x9a\xae\x1d\xa0\xeb\x9b\x65\xc8\xc7\xf8\xed\xc2\x3f\x76\xb7\x9e\x63\x46\x89\x17\xc3\xe9\xa0\xcc\x47\x3f\xe4\x13\x4b\x46\xb2\x82\x5c\xfa\x09\x55\xf2\xb7\xbf\xf8\xd8\x5f\xee\x54\x6a\x5e\xd9\xec\x84\x7a\xc0\x31\x05\xe7\x40\x27\xb6\x82\x90\xf1\x74\x65\xf7\xf3\x45\x4a\x5d\x6d\x97\xa7\x6b\x6c\x6c\x6c\xeb\x8a\xdf\x00\x00\x00\xff\xff\xfb\x53\x3e\x81\x6e\x01\x00\x00") func migrations6_create_assets_tableSqlBytes() ([]byte, error) { @@ -1518,6 +1539,7 @@ var _bindata = map[string]func() (*asset, error){ "migrations/59_remove_foreign_key_constraints.sql": migrations59_remove_foreign_key_constraintsSql, "migrations/5_create_trades_table.sql": migrations5_create_trades_tableSql, "migrations/60_add_asset_id_indexes.sql": migrations60_add_asset_id_indexesSql, + "migrations/61_trust_lines_by_account_type_code_issuer.sql": migrations61_trust_lines_by_account_type_code_issuerSql, "migrations/6_create_assets_table.sql": migrations6_create_assets_tableSql, "migrations/7_modify_trades_table.sql": migrations7_modify_trades_tableSql, "migrations/8_add_aggregators.sql": migrations8_add_aggregatorsSql, @@ -1626,6 +1648,7 @@ var _bintree = &bintree{nil, map[string]*bintree{ "59_remove_foreign_key_constraints.sql": &bintree{migrations59_remove_foreign_key_constraintsSql, map[string]*bintree{}}, "5_create_trades_table.sql": &bintree{migrations5_create_trades_tableSql, map[string]*bintree{}}, "60_add_asset_id_indexes.sql": &bintree{migrations60_add_asset_id_indexesSql, map[string]*bintree{}}, + "61_trust_lines_by_account_type_code_issuer.sql": &bintree{migrations61_trust_lines_by_account_type_code_issuerSql, map[string]*bintree{}}, "6_create_assets_table.sql": &bintree{migrations6_create_assets_tableSql, map[string]*bintree{}}, "7_modify_trades_table.sql": &bintree{migrations7_modify_trades_tableSql, map[string]*bintree{}}, "8_add_aggregators.sql": &bintree{migrations8_add_aggregatorsSql, map[string]*bintree{}}, diff --git a/services/horizon/internal/db2/schema/migrations/61_trust_lines_by_account_type_code_issuer.sql b/services/horizon/internal/db2/schema/migrations/61_trust_lines_by_account_type_code_issuer.sql new file mode 100644 index 0000000000..91afe0ca00 --- /dev/null +++ b/services/horizon/internal/db2/schema/migrations/61_trust_lines_by_account_type_code_issuer.sql @@ -0,0 +1,9 @@ +-- +migrate Up + +CREATE INDEX "trust_lines_by_type_code_issuer_account" ON trust_lines USING btree (asset_type, asset_code, asset_issuer, account_id); +DROP INDEX "trust_lines_by_type_code_issuer"; + +-- +migrate Down + +DROP INDEX "trust_lines_by_type_code_issuer_account"; +CREATE INDEX "trust_lines_by_type_code_issuer" ON trust_lines USING btree (asset_type, asset_code, asset_issuer);