Optimize the list active tags query

Some customers are hitting this endpoint rapidly for repositories with many, many tags. This change drops the unnecessary joins, which should reduce database load somewhat.
This commit is contained in:
Joseph Schorr 2019-01-14 13:34:25 -05:00
parent defd4b3b20
commit fe45797490
2 changed files with 20 additions and 12 deletions

View file

@ -204,18 +204,24 @@ def get_tag_manifest_digests(tags):
return {manifest.tag_id: manifest.digest for manifest in manifests}
def list_active_repo_tags(repo, start_id=None, limit=None):
def list_active_repo_tags(repo, start_id=None, limit=None, include_images=True):
""" Returns all of the active, non-hidden tags in a repository, joined to they images
and (if present), their manifest.
"""
query = _tag_alive(RepositoryTag
.select(RepositoryTag, Image, ImageStorage, TagManifest.digest)
.join(Image)
.join(ImageStorage)
.where(RepositoryTag.repository == repo, RepositoryTag.hidden == False)
.switch(RepositoryTag)
.join(TagManifest, JOIN.LEFT_OUTER)
.order_by(RepositoryTag.id))
if include_images:
query = _tag_alive(RepositoryTag
.select(RepositoryTag, Image, ImageStorage, TagManifest.digest)
.join(Image)
.join(ImageStorage)
.where(RepositoryTag.repository == repo, RepositoryTag.hidden == False)
.switch(RepositoryTag)
.join(TagManifest, JOIN.LEFT_OUTER)
.order_by(RepositoryTag.id))
else:
query = _tag_alive(RepositoryTag
.select(RepositoryTag)
.where(RepositoryTag.repository == repo, RepositoryTag.hidden == False)
.order_by(RepositoryTag.id))
if start_id is not None:
query = query.where(RepositoryTag.id >= start_id)

View file

@ -271,9 +271,11 @@ class PreOCIModel(SharedModel, RegistryDataInterface):
operation on repositories with a lot of tags, and should be avoided for more targetted
operations wherever possible.
"""
# NOTE: include_legacy_images isn't used here because `list_active_repo_tags` includes the
# information already, so we might as well just use it. However, the new model classes will
# *not* include it by default, so we make it a parameter now.
if not include_legacy_images:
tags = model.tag.list_active_repo_tags(repository_ref._db_id, start_pagination_id, limit,
include_images=False)
return [Tag.for_repository_tag(tag) for tag in tags]
tags = model.tag.list_active_repo_tags(repository_ref._db_id, start_pagination_id, limit)
return [Tag.for_repository_tag(tag,
legacy_image=LegacyImage.for_image(tag.image),