Improve performance of gallery and image queries (#2422)

* Revert to use FindByGalleryID in gallery resolver
* Sort by path in FindByGalleryID
* Optimise queries
This commit is contained in:
WithoutPants
2022-03-25 12:00:51 +11:00
committed by GitHub
parent 2d227edaf9
commit f581687198
5 changed files with 30 additions and 12 deletions

View File

@@ -28,7 +28,11 @@ func (r *galleryResolver) Images(ctx context.Context, obj *models.Gallery) (ret
var err error var err error
// #2376 - sort images by path // #2376 - sort images by path
ret, err = image.FindByGalleryID(repo.Image(), obj.ID, "path", models.SortDirectionEnumAsc) // doing this via Query is really slow, so stick with FindByGalleryID
ret, err = repo.Image().FindByGalleryID(obj.ID)
if err != nil {
return err
}
return err return err
}); err != nil { }); err != nil {
@@ -40,8 +44,8 @@ func (r *galleryResolver) Images(ctx context.Context, obj *models.Gallery) (ret
func (r *galleryResolver) Cover(ctx context.Context, obj *models.Gallery) (ret *models.Image, err error) { func (r *galleryResolver) Cover(ctx context.Context, obj *models.Gallery) (ret *models.Image, err error) {
if err := r.withReadTxn(ctx, func(repo models.ReaderRepository) error { if err := r.withReadTxn(ctx, func(repo models.ReaderRepository) error {
// #2376 - use first image (sorted by path) if no cover is present // doing this via Query is really slow, so stick with FindByGalleryID
imgs, err := image.FindByGalleryID(repo.Image(), obj.ID, "path", models.SortDirectionEnumAsc) imgs, err := repo.Image().FindByGalleryID(obj.ID)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -135,7 +135,7 @@ func (qb *galleryQueryBuilder) FindBySceneID(sceneID int) ([]*models.Gallery, er
func (qb *galleryQueryBuilder) FindByImageID(imageID int) ([]*models.Gallery, error) { func (qb *galleryQueryBuilder) FindByImageID(imageID int) ([]*models.Gallery, error) {
query := selectAll(galleryTable) + ` query := selectAll(galleryTable) + `
LEFT JOIN galleries_images as images_join on images_join.gallery_id = galleries.id INNER JOIN galleries_images as images_join on images_join.gallery_id = galleries.id
WHERE images_join.image_id = ? WHERE images_join.image_id = ?
GROUP BY galleries.id GROUP BY galleries.id
` `

View File

@@ -168,7 +168,12 @@ func (qb *imageQueryBuilder) FindByPath(path string) (*models.Image, error) {
func (qb *imageQueryBuilder) FindByGalleryID(galleryID int) ([]*models.Image, error) { func (qb *imageQueryBuilder) FindByGalleryID(galleryID int) ([]*models.Image, error) {
args := []interface{}{galleryID} args := []interface{}{galleryID}
return qb.queryImages(imagesForGalleryQuery+qb.getImageSort(nil), args) sort := "path"
sortDir := models.SortDirectionEnumAsc
return qb.queryImages(imagesForGalleryQuery+qb.getImageSort(&models.FindFilterType{
Sort: &sort,
Direction: &sortDir,
}), args)
} }
func (qb *imageQueryBuilder) CountByGalleryID(galleryID int) (int, error) { func (qb *imageQueryBuilder) CountByGalleryID(galleryID int) (int, error) {
@@ -413,8 +418,8 @@ func imageTagCountCriterionHandler(qb *imageQueryBuilder, tagCount *models.IntCr
func imageGalleriesCriterionHandler(qb *imageQueryBuilder, galleries *models.MultiCriterionInput) criterionHandlerFunc { func imageGalleriesCriterionHandler(qb *imageQueryBuilder, galleries *models.MultiCriterionInput) criterionHandlerFunc {
addJoinsFunc := func(f *filterBuilder) { addJoinsFunc := func(f *filterBuilder) {
qb.galleriesRepository().join(f, "galleries_join", "images.id") qb.galleriesRepository().join(f, "", "images.id")
f.addLeftJoin(galleryTable, "", "galleries_join.gallery_id = galleries.id") f.addLeftJoin(galleryTable, "", "galleries_images.gallery_id = galleries.id")
} }
h := qb.getMultiCriterionHandlerBuilder(galleryTable, galleriesImagesTable, galleryIDColumn, addJoinsFunc) h := qb.getMultiCriterionHandlerBuilder(galleryTable, galleriesImagesTable, galleryIDColumn, addJoinsFunc)

View File

@@ -713,8 +713,8 @@ func sceneStudioCriterionHandler(qb *sceneQueryBuilder, studios *models.Hierarch
func sceneMoviesCriterionHandler(qb *sceneQueryBuilder, movies *models.MultiCriterionInput) criterionHandlerFunc { func sceneMoviesCriterionHandler(qb *sceneQueryBuilder, movies *models.MultiCriterionInput) criterionHandlerFunc {
addJoinsFunc := func(f *filterBuilder) { addJoinsFunc := func(f *filterBuilder) {
qb.moviesRepository().join(f, "movies_join", "scenes.id") qb.moviesRepository().join(f, "", "scenes.id")
f.addLeftJoin("movies", "", "movies_join.movie_id = movies.id") f.addLeftJoin("movies", "", "movies_scenes.movie_id = movies.id")
} }
h := qb.getMultiCriterionHandlerBuilder(movieTable, moviesScenesTable, "movie_id", addJoinsFunc) h := qb.getMultiCriterionHandlerBuilder(movieTable, moviesScenesTable, "movie_id", addJoinsFunc)
return h.handler(movies) return h.handler(movies)

View File

@@ -194,11 +194,20 @@ func getMultiCriterionClause(primaryTable, foreignTable, joinTable, primaryFK, f
switch criterion.Modifier { switch criterion.Modifier {
case models.CriterionModifierIncludes: case models.CriterionModifierIncludes:
// includes any of the provided ids // includes any of the provided ids
if joinTable != "" {
whereClause = joinTable + "." + foreignFK + " IN " + getInBinding(len(criterion.Value))
} else {
whereClause = foreignTable + ".id IN " + getInBinding(len(criterion.Value)) whereClause = foreignTable + ".id IN " + getInBinding(len(criterion.Value))
}
case models.CriterionModifierIncludesAll: case models.CriterionModifierIncludesAll:
// includes all of the provided ids // includes all of the provided ids
if joinTable != "" {
whereClause = joinTable + "." + foreignFK + " IN " + getInBinding(len(criterion.Value))
havingClause = "count(distinct " + joinTable + "." + foreignFK + ") IS " + strconv.Itoa(len(criterion.Value))
} else {
whereClause = foreignTable + ".id IN " + getInBinding(len(criterion.Value)) whereClause = foreignTable + ".id IN " + getInBinding(len(criterion.Value))
havingClause = "count(distinct " + foreignTable + ".id) IS " + strconv.Itoa(len(criterion.Value)) havingClause = "count(distinct " + foreignTable + ".id) IS " + strconv.Itoa(len(criterion.Value))
}
case models.CriterionModifierExcludes: case models.CriterionModifierExcludes:
// excludes all of the provided ids // excludes all of the provided ids
if joinTable != "" { if joinTable != "" {