Skip to content

Commit

Permalink
attempt to ensure a better query execution plan for test run stats by…
Browse files Browse the repository at this point in the history
… forbidding hash joins (and some others)
  • Loading branch information
Pascal-Delange committed Jan 29, 2025
1 parent 8597f7a commit 1b6376a
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 31 deletions.
30 changes: 28 additions & 2 deletions repositories/rules.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,29 @@ func (repo *MarbleDbRepository) ListRulesByIterationId(ctx context.Context, exec
)
}

// This method expects to be run in a transaction, because we set some local settings
// that should not be changed for the whole connection.
func (repo *MarbleDbRepository) RulesExecutionStats(
ctx context.Context,
exec Executor,
exec Transaction,
organizationId string,
iterationId string,
begin, end time.Time,
) ([]models.RuleExecutionStat, error) {
if err := validateMarbleDbExecutor(exec); err != nil {
return nil, err
}

// The following settings are set because in some cases at least, the query planner
// has ended up choosing a query plan involving a hash join with a full table scan on decision_rules
_, err := exec.Exec(ctx,
`SET local join_collapse_limit = 1;
SET local enable_hashjoin = off;
SET local enable_mergejoin = off;`)
if err != nil {
return nil, err
}

query := NewQueryBuilder().
Select("scir.stable_rule_id, scir.name, dr.outcome, scit.version, COUNT(*) as total").
From("decisions as d").
Expand All @@ -80,16 +93,29 @@ func (repo *MarbleDbRepository) RulesExecutionStats(
)
}

// This method expects to be run in a transaction, because we set some local settings
// that should not be changed for the whole connection.
func (repo *MarbleDbRepository) PhanomRulesExecutionStats(
ctx context.Context,
exec Executor,
exec Transaction,
organizationId string,
iterationId string,
begin, end time.Time,
) ([]models.RuleExecutionStat, error) {
if err := validateMarbleDbExecutor(exec); err != nil {
return nil, err
}

// The following settings are set because in some cases at least, the query planner
// has ended up choosing a query plan involving a hash join with a full table scan on decision_rules
_, err := exec.Exec(ctx,
`SET local join_collapse_limit = 1;
SET local enable_hashjoin = off;
SET local enable_mergejoin = off;`)
if err != nil {
return nil, err
}

query := NewQueryBuilder().
Select("scir.stable_rule_id, scir.name, dr.outcome, scit.version, COUNT(*) as total").
From("phantom_decisions as d").
Expand Down
63 changes: 34 additions & 29 deletions usecases/rules_usecase.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ type RuleUsecaseRepository interface {
ListRulesByIterationId(ctx context.Context, exec repositories.Executor, iterationId string) ([]models.Rule, error)
RulesExecutionStats(
ctx context.Context,
exec repositories.Executor,
exec repositories.Transaction,
organizationId string,
iterationId string,
begin, end time.Time,
) ([]models.RuleExecutionStat, error)
PhanomRulesExecutionStats(
ctx context.Context,
exec repositories.Executor,
exec repositories.Transaction,
organizationId string,
iterationId string,
begin, end time.Time,
Expand Down Expand Up @@ -64,33 +64,38 @@ func (usecase *RuleUsecase) ListRules(ctx context.Context, iterationId string) (
}

func (usecase *RuleUsecase) ListRuleExecution(ctx context.Context, testrunId string) ([]models.RuleExecutionStat, error) {
exec := usecase.executorFactory.NewExecutor()
testrun, err := usecase.scenarioTestRunRepository.GetTestRunByID(ctx, exec, testrunId)
if err != nil {
return nil, err
}
rules, err := usecase.repository.PhanomRulesExecutionStats(
ctx,
exec,
testrun.OrganizationId,
testrun.ScenarioIterationId,
testrun.CreatedAt,
testrun.ExpiresAt)
if err != nil {
return nil, err
}
liveRules, err := usecase.repository.RulesExecutionStats(
ctx,
exec,
testrun.OrganizationId,
testrun.ScenarioLiveIterationId,
testrun.CreatedAt,
testrun.ExpiresAt)
if err != nil {
return nil, err
}
result := append(rules, liveRules...)
return result, nil
var result []models.RuleExecutionStat
err := usecase.transactionFactory.Transaction(ctx, func(tx repositories.Transaction) error {
testrun, err := usecase.scenarioTestRunRepository.GetTestRunByID(ctx, tx, testrunId)
if err != nil {
return err
}
rules, err := usecase.repository.PhanomRulesExecutionStats(
ctx,
tx,
testrun.OrganizationId,
testrun.ScenarioIterationId,
testrun.CreatedAt,
testrun.ExpiresAt)
if err != nil {
return err
}
result = append(result, rules...)

liveRules, err := usecase.repository.RulesExecutionStats(
ctx,
tx,
testrun.OrganizationId,
testrun.ScenarioLiveIterationId,
testrun.CreatedAt,
testrun.ExpiresAt)
if err != nil {
return err
}
result = append(result, liveRules...)
return nil
})
return result, err
}

func (usecase *RuleUsecase) CreateRule(ctx context.Context, ruleInput models.CreateRuleInput) (models.Rule, error) {
Expand Down

0 comments on commit 1b6376a

Please sign in to comment.