From 2a3c9742cc8fff409a7a3c5fe8cd13544165e10d Mon Sep 17 00:00:00 2001 From: InfiniteTF Date: Sun, 19 Apr 2020 04:03:51 +0200 Subject: [PATCH] Add slim endpoints for entities to speed up filters (#460) * Move performers image column to end of table * Remove redundant index --- graphql/documents/queries/misc.graphql | 8 +- graphql/schema/schema.graphql | 7 ++ pkg/api/resolver_query_find_movie.go | 5 + pkg/api/resolver_query_find_performer.go | 5 + pkg/api/resolver_query_find_studio.go | 5 + pkg/api/resolver_query_find_tag.go | 5 + pkg/database/database.go | 2 +- .../7_performer_optimization.up.sql | 101 ++++++++++++++++++ pkg/models/querybuilder_movies.go | 4 + pkg/models/querybuilder_performer.go | 4 + pkg/models/querybuilder_studio.go | 4 + pkg/models/querybuilder_tag.go | 6 +- .../Scenes/SceneDetails/SceneMovieTable.tsx | 4 +- ui/v2.5/src/components/Shared/Select.tsx | 8 +- 14 files changed, 156 insertions(+), 12 deletions(-) create mode 100644 pkg/database/migrations/7_performer_optimization.up.sql diff --git a/graphql/documents/queries/misc.graphql b/graphql/documents/queries/misc.graphql index 295532eef..2786ca997 100644 --- a/graphql/documents/queries/misc.graphql +++ b/graphql/documents/queries/misc.graphql @@ -19,24 +19,24 @@ query AllTags { } query AllPerformersForFilter { - allPerformers { + allPerformersSlim { ...SlimPerformerData } } query AllStudiosForFilter { - allStudios { + allStudiosSlim { ...SlimStudioData } } query AllMoviesForFilter { - allMovies { + allMoviesSlim { ...SlimMovieData } } query AllTagsForFilter { - allTags { + allTagsSlim { id name } diff --git a/graphql/schema/schema.graphql b/graphql/schema/schema.graphql index 201ed1d6e..77960ebf0 100644 --- a/graphql/schema/schema.graphql +++ b/graphql/schema/schema.graphql @@ -86,6 +86,13 @@ type Query { allMovies: [Movie!]! allTags: [Tag!]! + # Get everything with minimal metadata + + allPerformersSlim: [Performer!]! + allStudiosSlim: [Studio!]! + allMoviesSlim: [Movie!]! + allTagsSlim: [Tag!]! + # Version version: Version! diff --git a/pkg/api/resolver_query_find_movie.go b/pkg/api/resolver_query_find_movie.go index 4def160d3..bf983b2a0 100644 --- a/pkg/api/resolver_query_find_movie.go +++ b/pkg/api/resolver_query_find_movie.go @@ -26,3 +26,8 @@ func (r *queryResolver) AllMovies(ctx context.Context) ([]*models.Movie, error) qb := models.NewMovieQueryBuilder() return qb.All() } + +func (r *queryResolver) AllMoviesSlim(ctx context.Context) ([]*models.Movie, error) { + qb := models.NewMovieQueryBuilder() + return qb.AllSlim() +} diff --git a/pkg/api/resolver_query_find_performer.go b/pkg/api/resolver_query_find_performer.go index 33c29d6c5..efb694910 100644 --- a/pkg/api/resolver_query_find_performer.go +++ b/pkg/api/resolver_query_find_performer.go @@ -25,3 +25,8 @@ func (r *queryResolver) AllPerformers(ctx context.Context) ([]*models.Performer, qb := models.NewPerformerQueryBuilder() return qb.All() } + +func (r *queryResolver) AllPerformersSlim(ctx context.Context) ([]*models.Performer, error) { + qb := models.NewPerformerQueryBuilder() + return qb.AllSlim() +} diff --git a/pkg/api/resolver_query_find_studio.go b/pkg/api/resolver_query_find_studio.go index 3537254f8..4b39130f4 100644 --- a/pkg/api/resolver_query_find_studio.go +++ b/pkg/api/resolver_query_find_studio.go @@ -25,3 +25,8 @@ func (r *queryResolver) AllStudios(ctx context.Context) ([]*models.Studio, error qb := models.NewStudioQueryBuilder() return qb.All() } + +func (r *queryResolver) AllStudiosSlim(ctx context.Context) ([]*models.Studio, error) { + qb := models.NewStudioQueryBuilder() + return qb.AllSlim() +} diff --git a/pkg/api/resolver_query_find_tag.go b/pkg/api/resolver_query_find_tag.go index e5b6a5929..64fc866c9 100644 --- a/pkg/api/resolver_query_find_tag.go +++ b/pkg/api/resolver_query_find_tag.go @@ -16,3 +16,8 @@ func (r *queryResolver) AllTags(ctx context.Context) ([]*models.Tag, error) { qb := models.NewTagQueryBuilder() return qb.All() } + +func (r *queryResolver) AllTagsSlim(ctx context.Context) ([]*models.Tag, error) { + qb := models.NewTagQueryBuilder() + return qb.AllSlim() +} diff --git a/pkg/database/database.go b/pkg/database/database.go index 8d648671c..918ce9297 100644 --- a/pkg/database/database.go +++ b/pkg/database/database.go @@ -19,7 +19,7 @@ import ( var DB *sqlx.DB var dbPath string -var appSchemaVersion uint = 6 +var appSchemaVersion uint = 7 var databaseSchemaVersion uint const sqlite3Driver = "sqlite3_regexp" diff --git a/pkg/database/migrations/7_performer_optimization.up.sql b/pkg/database/migrations/7_performer_optimization.up.sql new file mode 100644 index 000000000..c09d3c4b4 --- /dev/null +++ b/pkg/database/migrations/7_performer_optimization.up.sql @@ -0,0 +1,101 @@ +DROP INDEX `performers_checksum_unique`; +DROP INDEX `index_performers_on_name`; +DROP INDEX `index_performers_on_checksum`; +ALTER TABLE `performers` RENAME TO `temp_old_performers`; +CREATE TABLE `performers` ( + `id` integer not null primary key autoincrement, + `checksum` varchar(255) not null, + `name` varchar(255), + `gender` varchar(20), + `url` varchar(255), + `twitter` varchar(255), + `instagram` varchar(255), + `birthdate` date, + `ethnicity` varchar(255), + `country` varchar(255), + `eye_color` varchar(255), + `height` varchar(255), + `measurements` varchar(255), + `fake_tits` varchar(255), + `career_length` varchar(255), + `tattoos` varchar(255), + `piercings` varchar(255), + `aliases` varchar(255), + `favorite` boolean not null default '0', + `created_at` datetime not null, + `updated_at` datetime not null, + `image` blob not null +); +CREATE UNIQUE INDEX `performers_checksum_unique` on `performers` (`checksum`); +CREATE INDEX `index_performers_on_name` on `performers` (`name`); +INSERT INTO `performers` ( + `id`, + `checksum`, + `name`, + `gender`, + `url`, + `twitter`, + `instagram`, + `birthdate`, + `ethnicity`, + `country`, + `eye_color`, + `height`, + `measurements`, + `fake_tits`, + `career_length`, + `tattoos`, + `piercings`, + `aliases`, + `favorite`, + `created_at`, + `updated_at`, + `image` +) +SELECT + `id`, + `checksum`, + `name`, + `gender`, + `url`, + `twitter`, + `instagram`, + `birthdate`, + `ethnicity`, + `country`, + `eye_color`, + `height`, + `measurements`, + `fake_tits`, + `career_length`, + `tattoos`, + `piercings`, + `aliases`, + `favorite`, + `created_at`, + `updated_at`, + `image` +FROM `temp_old_performers`; + +DROP INDEX `index_performers_scenes_on_scene_id`; +DROP INDEX `index_performers_scenes_on_performer_id`; +ALTER TABLE performers_scenes RENAME TO temp_old_performers_scenes; +CREATE TABLE `performers_scenes` ( + `performer_id` integer, + `scene_id` integer, + foreign key(`performer_id`) references `performers`(`id`), + foreign key(`scene_id`) references `scenes`(`id`) +); +CREATE INDEX `index_performers_scenes_on_scene_id` on `performers_scenes` (`scene_id`); +CREATE INDEX `index_performers_scenes_on_performer_id` on `performers_scenes` (`performer_id`); +INSERT INTO `performers_scenes` ( + `performer_id`, + `scene_id` +) +SELECT + `performer_id`, + `scene_id` +FROM `temp_old_performers_scenes`; + +DROP TABLE `temp_old_performers`; +DROP TABLE `temp_old_performers_scenes`; diff --git a/pkg/models/querybuilder_movies.go b/pkg/models/querybuilder_movies.go index edc732986..37b579af4 100644 --- a/pkg/models/querybuilder_movies.go +++ b/pkg/models/querybuilder_movies.go @@ -109,6 +109,10 @@ func (qb *MovieQueryBuilder) All() ([]*Movie, error) { return qb.queryMovies(selectAll("movies")+qb.getMovieSort(nil), nil, nil) } +func (qb *MovieQueryBuilder) AllSlim() ([]*Movie, error) { + return qb.queryMovies("SELECT movies.id, movies.name FROM movies "+qb.getMovieSort(nil), nil, nil) +} + func (qb *MovieQueryBuilder) Query(findFilter *FindFilterType) ([]*Movie, int) { if findFilter == nil { findFilter = &FindFilterType{} diff --git a/pkg/models/querybuilder_performer.go b/pkg/models/querybuilder_performer.go index 06fdc9b7e..fb73985fb 100644 --- a/pkg/models/querybuilder_performer.go +++ b/pkg/models/querybuilder_performer.go @@ -105,6 +105,10 @@ func (qb *PerformerQueryBuilder) All() ([]*Performer, error) { return qb.queryPerformers(selectAll("performers")+qb.getPerformerSort(nil), nil, nil) } +func (qb *PerformerQueryBuilder) AllSlim() ([]*Performer, error) { + return qb.queryPerformers("SELECT performers.id, performers.name, performers.gender FROM performers "+qb.getPerformerSort(nil), nil, nil) +} + func (qb *PerformerQueryBuilder) Query(performerFilter *PerformerFilterType, findFilter *FindFilterType) ([]*Performer, int) { if performerFilter == nil { performerFilter = &PerformerFilterType{} diff --git a/pkg/models/querybuilder_studio.go b/pkg/models/querybuilder_studio.go index da33979e6..058ea2fad 100644 --- a/pkg/models/querybuilder_studio.go +++ b/pkg/models/querybuilder_studio.go @@ -93,6 +93,10 @@ func (qb *StudioQueryBuilder) All() ([]*Studio, error) { return qb.queryStudios(selectAll("studios")+qb.getStudioSort(nil), nil, nil) } +func (qb *StudioQueryBuilder) AllSlim() ([]*Studio, error) { + return qb.queryStudios("SELECT studios.id, studios.name FROM studios "+qb.getStudioSort(nil), nil, nil) +} + func (qb *StudioQueryBuilder) Query(findFilter *FindFilterType) ([]*Studio, int) { if findFilter == nil { findFilter = &FindFilterType{} diff --git a/pkg/models/querybuilder_tag.go b/pkg/models/querybuilder_tag.go index 0b0142939..9a8f11a27 100644 --- a/pkg/models/querybuilder_tag.go +++ b/pkg/models/querybuilder_tag.go @@ -33,7 +33,7 @@ func (qb *TagQueryBuilder) Create(newTag Tag, tx *sqlx.Tx) (*Tag, error) { if err := tx.Get(&newTag, `SELECT * FROM tags WHERE id = ? LIMIT 1`, studioID); err != nil { return nil, err } - + return &newTag, nil } @@ -136,6 +136,10 @@ func (qb *TagQueryBuilder) All() ([]*Tag, error) { return qb.queryTags(selectAll("tags")+qb.getTagSort(nil), nil, nil) } +func (qb *TagQueryBuilder) AllSlim() ([]*Tag, error) { + return qb.queryTags("SELECT tags.id, tags.name FROM tags "+qb.getTagSort(nil), nil, nil) +} + func (qb *TagQueryBuilder) Query(findFilter *FindFilterType) ([]*Tag, int) { if findFilter == nil { findFilter = &FindFilterType{} diff --git a/ui/v2.5/src/components/Scenes/SceneDetails/SceneMovieTable.tsx b/ui/v2.5/src/components/Scenes/SceneDetails/SceneMovieTable.tsx index 23d83e671..6f27512f0 100644 --- a/ui/v2.5/src/components/Scenes/SceneDetails/SceneMovieTable.tsx +++ b/ui/v2.5/src/components/Scenes/SceneDetails/SceneMovieTable.tsx @@ -17,11 +17,11 @@ export const SceneMovieTable: React.FunctionComponent = ( ) => { const { data } = StashService.useAllMoviesForFilter(); - const items = !!data && !!data.allMovies ? data.allMovies : []; + const items = !!data && !!data.allMoviesSlim ? data.allMoviesSlim : []; let itemsFilter: ValidTypes[] = []; if (!!props.movieSceneIndexes && !!items) { - props.movieSceneIndexes.forEach((index, movieId) => { + props.movieSceneIndexes.forEach((_index, movieId) => { itemsFilter = itemsFilter.concat(items.filter((x) => x.id === movieId)); }); } diff --git a/ui/v2.5/src/components/Shared/Select.tsx b/ui/v2.5/src/components/Shared/Select.tsx index d972a06af..447b47ce9 100644 --- a/ui/v2.5/src/components/Shared/Select.tsx +++ b/ui/v2.5/src/components/Shared/Select.tsx @@ -183,7 +183,7 @@ export const FilterSelect: React.FC = (props) => export const PerformerSelect: React.FC = (props) => { const { data, loading } = StashService.useAllPerformersForFilter(); - const normalizedData = data?.allPerformers ?? []; + const normalizedData = data?.allPerformersSlim ?? []; const items: Option[] = normalizedData.map((item) => ({ value: item.id, label: item.name ?? "", @@ -216,7 +216,7 @@ export const PerformerSelect: React.FC = (props) => { export const StudioSelect: React.FC = (props) => { const { data, loading } = StashService.useAllStudiosForFilter(); - const normalizedData = data?.allStudios ?? []; + const normalizedData = data?.allStudiosSlim ?? []; const items = (normalizedData.length > 0 ? [{ name: "None", id: "0" }, ...normalizedData] @@ -254,7 +254,7 @@ export const StudioSelect: React.FC = (props) => { export const MovieSelect: React.FC = (props) => { const { data, loading } = StashService.useAllMoviesForFilter(); - const normalizedData = data?.allMovies ?? []; + const normalizedData = data?.allMoviesSlim ?? []; const items = (normalizedData.length > 0 ? [{ name: "None", id: "0" }, ...normalizedData] @@ -299,7 +299,7 @@ export const TagSelect: React.FC = (props) => { const selectedTags = props.ids ?? selectedIds; - const tags = data?.allTags ?? []; + const tags = data?.allTagsSlim ?? []; const selected = tags .filter((tag) => selectedTags.indexOf(tag.id) !== -1) .map((tag) => ({ value: tag.id, label: tag.name }));