From 4e9e97494cc520a1a8ec5d6a9445139a21e9d85c Mon Sep 17 00:00:00 2001 From: Yosuke Otosu <15183665+purplesmoke05@users.noreply.github.com> Date: Wed, 26 Feb 2025 13:47:34 +0900 Subject: [PATCH] Add SQL INDEX to optimize token holders API performance (#766) --- app/model/db/idx_personal_info.py | 11 ++- app/model/db/idx_position.py | 37 ++++++- .../40e3e7206fbc_v25_3_0_fix_763_2.py | 98 +++++++++++++++++++ 3 files changed, 144 insertions(+), 2 deletions(-) create mode 100644 migrations/versions/40e3e7206fbc_v25_3_0_fix_763_2.py diff --git a/app/model/db/idx_personal_info.py b/app/model/db/idx_personal_info.py index f5730eec..b1192126 100644 --- a/app/model/db/idx_personal_info.py +++ b/app/model/db/idx_personal_info.py @@ -21,7 +21,7 @@ from enum import StrEnum import pytz -from sqlalchemy import JSON, BigInteger, DateTime, String +from sqlalchemy import JSON, BigInteger, DateTime, Index, String from sqlalchemy.ext.hybrid import hybrid_property from sqlalchemy.orm import Mapped, mapped_column @@ -64,6 +64,15 @@ class IDXPersonalInfo(Base): String(10), nullable=False ) + __table_args__ = ( + Index( + "idx_personal_info_issuer_account", + issuer_address, + account_address, + postgresql_include=["personal_info", "data_source", "created", "modified"], + ), + ) + @hybrid_property def personal_info(self): if self._personal_info: diff --git a/app/model/db/idx_position.py b/app/model/db/idx_position.py index 22ad382d..a5e2c3ac 100644 --- a/app/model/db/idx_position.py +++ b/app/model/db/idx_position.py @@ -17,7 +17,7 @@ SPDX-License-Identifier: Apache-2.0 """ -from sqlalchemy import BigInteger, String +from sqlalchemy import BigInteger, Index, String from sqlalchemy.orm import Mapped, mapped_column from .base import Base @@ -41,6 +41,31 @@ class IDXPosition(Base): # pendingTransfer pending_transfer: Mapped[int | None] = mapped_column(BigInteger) + __table_args__ = ( + Index( + "idx_position_token_account_value", + token_address, + account_address, + balance, + exchange_balance, + pending_transfer, + exchange_commitment, + ), + Index( + "idx_position_token_account", + token_address, + account_address, + postgresql_include=[ + "balance", + "exchange_balance", + "exchange_commitment", + "pending_transfer", + "created", + "modified", + ], + ), + ) + def json(self): return { "account_address": self.account_address, @@ -87,6 +112,16 @@ class IDXLockedPosition(Base): # locked amount value: Mapped[int] = mapped_column(BigInteger, nullable=False) + __table_args__ = ( + Index( + "idx_locked_position_token_account_value_modified", + token_address, + account_address, + value, + "modified", + ), + ) + def json(self): return { "token_address": self.token_address, diff --git a/migrations/versions/40e3e7206fbc_v25_3_0_fix_763_2.py b/migrations/versions/40e3e7206fbc_v25_3_0_fix_763_2.py new file mode 100644 index 00000000..b487a47f --- /dev/null +++ b/migrations/versions/40e3e7206fbc_v25_3_0_fix_763_2.py @@ -0,0 +1,98 @@ +"""v25_3_0_fix_763_2 + +Revision ID: 40e3e7206fbc +Revises: 18506373ccd3 +Create Date: 2025-02-26 12:33:20.263287 + +""" + +from alembic import op +import sqlalchemy as sa + + +from app.database import get_db_schema + +# revision identifiers, used by Alembic. +revision = "40e3e7206fbc" +down_revision = "18506373ccd3" +branch_labels = None +depends_on = None + + +def upgrade(): + op.create_index( + "idx_locked_position_token_account_value_modified", + "idx_locked_position", + ["token_address", "account_address", "value", "modified"], + unique=False, + schema=get_db_schema(), + ) + op.create_index( + "idx_personal_info_issuer_account", + "idx_personal_info", + ["issuer_address", "account_address"], + unique=False, + postgresql_include=["personal_info", "data_source", "created", "modified"], + schema=get_db_schema(), + ) + op.create_index( + "idx_position_token_account", + "idx_position", + ["token_address", "account_address"], + unique=False, + postgresql_include=[ + "balance", + "exchange_balance", + "exchange_commitment", + "pending_transfer", + "created", + "modified", + ], + schema=get_db_schema(), + ) + op.create_index( + "idx_position_token_account_value", + "idx_position", + [ + "token_address", + "account_address", + "balance", + "exchange_balance", + "pending_transfer", + "exchange_commitment", + ], + unique=False, + schema=get_db_schema(), + ) + + +def downgrade(): + op.drop_index( + "idx_position_token_account_value", + table_name="idx_position", + schema=get_db_schema(), + ) + op.drop_index( + "idx_position_token_account", + table_name="idx_position", + postgresql_include=[ + "balance", + "exchange_balance", + "exchange_commitment", + "pending_transfer", + "created", + "modified", + ], + schema=get_db_schema(), + ) + op.drop_index( + "idx_personal_info_issuer_account", + table_name="idx_personal_info", + postgresql_include=["personal_info", "data_source", "created", "modified"], + schema=get_db_schema(), + ) + op.drop_index( + "idx_locked_position_token_account_value_modified", + table_name="idx_locked_position", + schema=get_db_schema(), + )