Skip to content

Commit 3ae29dc

Browse files
authored
Add indexes (#180)
Signed-off-by: kerthcet <kerthcet@gmail.com>
1 parent 52764e4 commit 3ae29dc

2 files changed

Lines changed: 102 additions & 4 deletions

File tree

alphatrion/storage/sql_models.py

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,16 @@
22
import uuid
33
from datetime import UTC, datetime
44

5-
from sqlalchemy import JSON, Column, DateTime, Float, Integer, String, UniqueConstraint
5+
from sqlalchemy import (
6+
JSON,
7+
Column,
8+
DateTime,
9+
Float,
10+
Index,
11+
Integer,
12+
String,
13+
UniqueConstraint,
14+
)
615
from sqlalchemy.dialects.postgresql import UUID
716
from sqlalchemy.ext.mutable import MutableDict
817
from sqlalchemy.orm import declarative_base
@@ -79,7 +88,7 @@ class TeamMember(Base):
7988

8089
uuid = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
8190
team_id = Column(UUID(as_uuid=True), nullable=False)
82-
user_id = Column(UUID(as_uuid=True), nullable=False)
91+
user_id = Column(UUID(as_uuid=True), nullable=False, index=True)
8392

8493
created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(UTC))
8594
updated_at = Column(
@@ -88,7 +97,11 @@ class TeamMember(Base):
8897
onupdate=lambda: datetime.now(UTC),
8998
)
9099

91-
__table_args__ = (UniqueConstraint("team_id", "user_id", name="unique_team_user"),)
100+
__table_args__ = (
101+
# Prevents duplicate team memberships and creates index on (team_id, user_id)
102+
# This index covers queries filtering by team_id (via leftmost prefix rule)
103+
UniqueConstraint("team_id", "user_id", name="unique_team_user"),
104+
)
92105

93106

94107
class ExperimentType(enum.IntEnum):
@@ -140,6 +153,17 @@ class Experiment(Base):
140153
)
141154
is_del = Column(Integer, default=0, comment="0 for not deleted, 1 for deleted")
142155

156+
__table_args__ = (
157+
# For get_exp_by_name() - line 407-412: (team_id, name, is_del)
158+
Index("idx_experiment_team_name", "team_id", "name", "is_del"),
159+
# For list_exps_by_team_id() - line 428-429: (team_id, is_del) +
160+
# ORDER BY created_at
161+
# For list_exps_by_timeframe() - line 521-528: (team_id, created_at range,
162+
# is_del)
163+
# For count_experiments() - line 507-515: (team_id, is_del)
164+
Index("idx_experiment_team_active_time", "team_id", "is_del", "created_at"),
165+
)
166+
143167

144168
class Run(Base):
145169
__tablename__ = "runs"
@@ -170,6 +194,14 @@ class Run(Base):
170194
)
171195
is_del = Column(Integer, default=0, comment="0 for not deleted, 1 for deleted")
172196

197+
__table_args__ = (
198+
# For list_runs_by_exp_id() - line 592: (experiment_id, is_del) +
199+
# ORDER BY created_at
200+
Index("idx_run_experiment_active", "experiment_id", "is_del", "created_at"),
201+
# For count_runs() - line 606: (team_id, is_del)
202+
Index("idx_run_team_active", "team_id", "is_del"),
203+
)
204+
173205

174206
# class Model(Base):
175207
# __tablename__ = "models"
@@ -196,7 +228,6 @@ class Run(Base):
196228

197229
class Metric(Base):
198230
__tablename__ = "metrics"
199-
__table_args__ = (UniqueConstraint("run_id", "key", name="idx_unique_metric"),)
200231

201232
uuid = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
202233
key = Column(String, nullable=False)
@@ -206,6 +237,17 @@ class Metric(Base):
206237
run_id = Column(UUID(as_uuid=True), nullable=False)
207238
created_at = Column(DateTime(timezone=True), default=datetime.now(UTC))
208239

240+
__table_args__ = (
241+
# For list_metrics_by_experiment_id() - line 639: filter + ORDER BY created_at
242+
Index("idx_metric_experiment_time", "experiment_id", "created_at"),
243+
# For list_metrics_by_run_id() - line 650: filter + ORDER BY created_at
244+
# Note: UniqueConstraint below provides (run_id, key) index, but not optimal
245+
# for ORDER BY created_at
246+
Index("idx_metric_run_time", "run_id", "created_at"),
247+
# Unique constraint for data integrity
248+
UniqueConstraint("run_id", "key", name="idx_unique_metric"),
249+
)
250+
209251

210252
class ExperimentLabel(Base):
211253
__tablename__ = "experiment_labels"
@@ -222,3 +264,13 @@ class ExperimentLabel(Base):
222264
default=lambda: datetime.now(UTC),
223265
onupdate=lambda: datetime.now(UTC),
224266
)
267+
268+
__table_args__ = (
269+
# For list_labels_by_exp_id() - line 446: filter by experiment_id
270+
# For list_exps_by_label() join - line 464-474: join + filter by
271+
# label_name/value
272+
# This composite index covers both via leftmost prefix rule
273+
Index(
274+
"idx_experiment_label_lookup", "experiment_id", "label_name", "label_value"
275+
),
276+
)
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
"""add indexes
2+
3+
Revision ID: 766c8b7fe6c5
4+
Revises: 344adc5da83a
5+
Create Date: 2026-03-02 12:22:37.129491
6+
7+
"""
8+
from typing import Sequence, Union
9+
10+
from alembic import op
11+
import sqlalchemy as sa
12+
13+
14+
# revision identifiers, used by Alembic.
15+
revision: str = '766c8b7fe6c5'
16+
down_revision: Union[str, Sequence[str], None] = '344adc5da83a'
17+
branch_labels: Union[str, Sequence[str], None] = None
18+
depends_on: Union[str, Sequence[str], None] = None
19+
20+
21+
def upgrade() -> None:
22+
"""Upgrade schema."""
23+
# ### commands auto generated by Alembic - please adjust! ###
24+
op.create_index('idx_experiment_label_lookup', 'experiment_labels', ['experiment_id', 'label_name', 'label_value'], unique=False)
25+
op.create_index('idx_experiment_team_active_time', 'experiments', ['team_id', 'is_del', 'created_at'], unique=False)
26+
op.create_index('idx_experiment_team_name', 'experiments', ['team_id', 'name', 'is_del'], unique=False)
27+
op.create_index('idx_metric_experiment_time', 'metrics', ['experiment_id', 'created_at'], unique=False)
28+
op.create_index('idx_metric_run_time', 'metrics', ['run_id', 'created_at'], unique=False)
29+
op.create_index('idx_run_experiment_active', 'runs', ['experiment_id', 'is_del', 'created_at'], unique=False)
30+
op.create_index('idx_run_team_active', 'runs', ['team_id', 'is_del'], unique=False)
31+
op.create_index(op.f('ix_team_members_user_id'), 'team_members', ['user_id'], unique=False)
32+
# ### end Alembic commands ###
33+
34+
35+
def downgrade() -> None:
36+
"""Downgrade schema."""
37+
# ### commands auto generated by Alembic - please adjust! ###
38+
op.drop_index(op.f('ix_team_members_user_id'), table_name='team_members')
39+
op.drop_index('idx_run_team_active', table_name='runs')
40+
op.drop_index('idx_run_experiment_active', table_name='runs')
41+
op.drop_index('idx_metric_run_time', table_name='metrics')
42+
op.drop_index('idx_metric_experiment_time', table_name='metrics')
43+
op.drop_index('idx_experiment_team_name', table_name='experiments')
44+
op.drop_index('idx_experiment_team_active_time', table_name='experiments')
45+
op.drop_index('idx_experiment_label_lookup', table_name='experiment_labels')
46+
# ### end Alembic commands ###

0 commit comments

Comments
 (0)