22import uuid
33from 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+ )
615from sqlalchemy .dialects .postgresql import UUID
716from sqlalchemy .ext .mutable import MutableDict
817from 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
94107class 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
144168class 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
197229class 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
210252class 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+ )
0 commit comments