Skip to content

Commit 03eb642

Browse files
committed
perf(gen): use JOIN DISTINCT unnest(...) for composite-key loaders on psql
Composite-key relationship loaders and LoadCount used `(a, b) IN (SELECT unnest($1), unnest($2))`, which mis-estimates row counts and forces a Seq Scan + Hash Semi Join. Switch to an INNER JOIN on a DISTINCT unnest so the planner can use an indexed nested loop. Single-column keys are unchanged.
1 parent f475b48 commit 03eb642

2 files changed

Lines changed: 57 additions & 14 deletions

File tree

gen/templates/counts/table/115_counts.go.tpl

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -208,13 +208,6 @@ func (os {{$tAlias.UpSingular}}Slice) LoadCount{{$relAlias}}(ctx context.Context
208208
{{- $fromCol := index $firstFrom.Columns $local}}
209209
PKArgExpr := {{$.Dialect}}.Any({{$.Dialect}}.Cast({{$.Dialect}}.Arg(pk{{$fromCol}}), "{{$column.DBType}}[]"))
210210
{{- else}}
211-
PKArgExpr := {{$.Dialect}}.Select(sm.Columns(
212-
{{- range $index, $local := $firstSide.FromColumns -}}
213-
{{- $column := $.Table.GetColumn $local -}}
214-
{{- $fromCol := index $firstFrom.Columns $local}}
215-
{{$.Dialect}}.F("unnest", {{$.Dialect}}.Cast({{$.Dialect}}.Arg(pk{{$fromCol}}), "{{$column.DBType}}[]")),
216-
{{- end}}
217-
))
218211
{{- end}}
219212
{{- end}}
220213

@@ -286,6 +279,36 @@ func (os {{$tAlias.UpSingular}}Slice) LoadCount{{$relAlias}}(ctx context.Context
286279
{{- else -}}
287280
sm.Where({{$firstTo.UpPlural}}.Columns.{{$firstToColAlias}}.OP("IN", PKArgExpr)),
288281
{{- end}}
282+
{{- else if eq $.Dialect "psql" -}}
283+
sm.InnerJoin({{$.Dialect}}.Select(
284+
sm.Distinct(),
285+
sm.Columns(
286+
{{range $index, $local := $firstSide.FromColumns -}}
287+
{{$toLocal := index $firstSide.ToColumns $index -}}
288+
{{$firstToColAlias := index $firstTo.Columns $toLocal -}}
289+
{{$.Dialect}}.Quote("bob_rel_keys_src", {{quote $firstToColAlias}}),
290+
{{end -}}
291+
),
292+
sm.From({{$.Dialect}}.F("unnest",
293+
{{range $index, $local := $firstSide.FromColumns -}}
294+
{{$column := $.Table.GetColumn $local -}}
295+
{{$fromCol := index $firstFrom.Columns $local -}}
296+
{{$.Dialect}}.Cast({{$.Dialect}}.Arg(pk{{$fromCol}}), "{{$column.DBType}}[]"),
297+
{{end -}}
298+
)).As("bob_rel_keys_src"
299+
{{- range $index, $local := $firstSide.FromColumns -}}
300+
{{- $toLocal := index $firstSide.ToColumns $index -}}
301+
{{- $firstToColAlias := index $firstTo.Columns $toLocal -}}
302+
, {{quote $firstToColAlias}}
303+
{{- end -}}
304+
),
305+
)).As("bob_rel_keys").On(
306+
{{range $index, $local := $firstSide.FromColumns -}}
307+
{{$toLocal := index $firstSide.ToColumns $index -}}
308+
{{$firstToColAlias := index $firstTo.Columns $toLocal -}}
309+
{{$firstTo.UpPlural}}.Columns.{{$firstToColAlias}}.EQ({{$.Dialect}}.Quote("bob_rel_keys", {{quote $firstToColAlias}})),
310+
{{end -}}
311+
),
289312
{{- else -}}
290313
sm.Where({{$.Dialect}}.Group(
291314
{{range $index, $local := $firstSide.FromColumns -}}

gen/templates/models/table/009_rel_query.go.tpl

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -93,13 +93,6 @@ func (os {{$tAlias.UpSingular}}Slice) {{relQueryMethodName $tAlias $relAlias}}(m
9393
{{- $fromCol := index $firstFrom.Columns $local}}
9494
PKArgExpr := psql.Any(psql.Cast(psql.Arg(pk{{$fromCol}}), "{{$column.DBType}}[]"))
9595
{{else}}
96-
PKArgExpr := psql.Select(sm.Columns(
97-
{{- range $index, $local := $firstSide.FromColumns -}}
98-
{{$column := $.Table.GetColumn $local}}
99-
{{$fromCol := index $firstFrom.Columns $local -}}
100-
psql.F("unnest", psql.Cast(psql.Arg(pk{{$fromCol}}), "{{$column.DBType}}[]")),
101-
{{- end}}
102-
))
10396
{{end}}
10497
{{end}}
10598
{{- end}}
@@ -135,6 +128,33 @@ func (os {{$tAlias.UpSingular}}Slice) {{relQueryMethodName $tAlias $relAlias}}(m
135128
{{if and (eq $.Dialect "psql") (eq (len $side.FromColumns) 1) -}}
136129
{{- $toCol := index $to.Columns (index $side.ToColumns 0) -}}
137130
sm.Where({{$to.UpPlural}}.Columns.{{$toCol}}.EQ(PKArgExpr)),
131+
{{- else if eq $.Dialect "psql" -}}
132+
sm.InnerJoin(psql.Select(
133+
sm.Distinct(),
134+
sm.Columns(
135+
{{- range $index, $local := $side.FromColumns -}}
136+
{{- $toCol := index $to.Columns (index $side.ToColumns $index) -}}
137+
psql.Quote("bob_rel_keys_src", {{quote $toCol}}),
138+
{{- end}}
139+
),
140+
sm.From(psql.F("unnest",
141+
{{- range $index, $local := $side.FromColumns -}}
142+
{{- $fromCol := index $from.Columns $local -}}
143+
{{- $column := $.Table.GetColumn $local -}}
144+
psql.Cast(psql.Arg(pk{{$fromCol}}), "{{$column.DBType}}[]"),
145+
{{- end}}
146+
)).As("bob_rel_keys_src"
147+
{{- range $index, $local := $side.FromColumns -}}
148+
{{- $toCol := index $to.Columns (index $side.ToColumns $index) -}}
149+
, {{quote $toCol}}
150+
{{- end -}}
151+
),
152+
)).As("bob_rel_keys").On(
153+
{{- range $index, $local := $side.FromColumns -}}
154+
{{- $toCol := index $to.Columns (index $side.ToColumns $index) -}}
155+
{{$to.UpPlural}}.Columns.{{$toCol}}.EQ(psql.Quote("bob_rel_keys", {{quote $toCol}})),
156+
{{- end}}
157+
),
138158
{{- else -}}
139159
sm.Where({{$.Dialect}}.Group(
140160
{{- range $index, $local := $side.FromColumns -}}

0 commit comments

Comments
 (0)