diff --git a/pkg/database/database.go b/pkg/database/database.go index edb8c99ec..eacf25a3d 100644 --- a/pkg/database/database.go +++ b/pkg/database/database.go @@ -4,7 +4,7 @@ import ( "github.com/jmoiron/sqlx" ) -var appSchemaVersion uint = 31 +var appSchemaVersion uint = 32 var databaseProviders map[string]databaseProvider diff --git a/pkg/database/migrations/postgres/32_edit_indexes.up.sql b/pkg/database/migrations/postgres/32_edit_indexes.up.sql new file mode 100644 index 000000000..f835e8d2c --- /dev/null +++ b/pkg/database/migrations/postgres/32_edit_indexes.up.sql @@ -0,0 +1,9 @@ +CREATE INDEX "edit_votes_user_edit_idx" ON "edit_votes" ("user_id", "edit_id"); +CREATE INDEX "edit_status_idx" ON edits ("status"); +CREATE INDEX "edit_comments_edit_idx" ON "edit_comments" ("edit_id"); +CREATE INDEX "scene_edits_scene_idx" ON "scene_edits" ("scene_id"); +CREATE INDEX "scene_edits_edit_idx" ON "scene_edits" ("edit_id"); +CREATE INDEX "performer_edits_edit_idx" ON "performer_edits" ("edit_id"); +CREATE INDEX "tag_edits_edit_idx" ON "tag_edits" ("edit_id"); +CREATE INDEX "studio_edits_edit_idx" ON "studio_edits" ("edit_id"); +CREATE INDEX "studio_deleted_parent_idx" ON "studios" ("deleted", "parent_studio_id"); diff --git a/pkg/sqlx/querybuilder_edit.go b/pkg/sqlx/querybuilder_edit.go index 7521aeb1e..139463d0b 100644 --- a/pkg/sqlx/querybuilder_edit.go +++ b/pkg/sqlx/querybuilder_edit.go @@ -217,22 +217,23 @@ func (qb *editQueryBuilder) buildQuery(filter models.EditQueryInput, userID uuid if filter.TargetType == nil || *filter.TargetType == "" { return nil, errors.New("TargetType is required when TargetID filter is used") } - switch *filter.TargetType { - case models.TargetTypeEnumTag: - query.AddJoin(editTagTable.table, editTagTable.Name()+".edit_id = edits.id") - query.AddWhere("(" + editTagTable.Name() + ".tag_id = ? OR " + editDBTable.Name() + ".data->'merge_sources' @> ?)") - case models.TargetTypeEnumPerformer: - query.AddJoin(editPerformerTable.table, editPerformerTable.Name()+".edit_id = edits.id") - query.AddWhere("(" + editPerformerTable.Name() + ".performer_id = ? OR " + editDBTable.Name() + ".data->'merge_sources' @> ?)") - case models.TargetTypeEnumStudio: - query.AddJoin(editStudioTable.table, editStudioTable.Name()+".edit_id = edits.id") - query.AddWhere("(" + editStudioTable.Name() + ".studio_id = ? OR " + editDBTable.Name() + ".data->'merge_sources' @> ?)") - case models.TargetTypeEnumScene: - query.AddJoin(editSceneTable.table, editSceneTable.Name()+".edit_id = edits.id") - query.AddWhere("(" + editSceneTable.Name() + ".scene_id = ? OR " + editDBTable.Name() + ".data->'merge_sources' @> ?)") - } + + // Union is significantly faster than an OR query + query.AddWhere(fmt.Sprintf(` + edits.id IN ( + SELECT id + FROM edits E + WHERE E.data->'merge_sources' @> ? + UNION + SELECT id + FROM edits E + JOIN %[1]s_edits TJ ON TJ.edit_id = E.id + WHERE TJ.%[1]s_id = ? + ) + `, strings.ToLower(filter.TargetType.String()))) + jsonID, _ := json.Marshal(*targetID) - query.AddArg(*targetID, jsonID) + query.AddArg(jsonID, *targetID) } else if q := filter.TargetType; q != nil && *q != "" { query.Eq("target_type", q.String()) }