mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 12:24:38 +03:00
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:
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
`
|
`
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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 != "" {
|
||||||
|
|||||||
Reference in New Issue
Block a user