Remove double join in provider_ids_from_rp_ids

provider_ids_from_rp_ids is only used in _build_provider_summaries.
It is passed a collection of usages dict created
_get_usages_by_provider_tree this has usage information for _all_
the providers in the contributing trees, even those providers that
do not provide any resources (otherwise we wouldn't be able to
build a complete summary).

This means that the list of rp ids passed to provider_ids_from_rp_ids
includes all the relevant rps and the returned data structure can
itself be used to find root_provider_uuid and parent_provider_uuid,
instead of doing the join.

This speeds up the database query. Combined with the expanding
bindparam in the previous patch, this cleans up provider_ids_from_rp_ids
nicely.

Change-Id: If937053a8af3f0eecdd90aa807be0abc316d8c4f
This commit is contained in:
Chris Dent
2019-08-01 13:17:07 +01:00
parent 0386f53407
commit 8da825efc9
2 changed files with 8 additions and 21 deletions

View File

@@ -508,11 +508,13 @@ def _build_provider_summaries(context, rw_ctx, usages, prov_traits):
summary = rw_ctx.summaries_by_id.get(rp_id)
if not summary:
pids = provider_ids[rp_id]
parent_id = pids.parent_id
parent_uuid = provider_ids[parent_id].uuid if parent_id else None
summary = ProviderSummary(
resource_provider=rp_obj.ResourceProvider(
context, id=pids.id, uuid=pids.uuid,
root_provider_uuid=pids.root_uuid,
parent_provider_uuid=pids.parent_uuid),
root_provider_uuid=provider_ids[pids.root_id].uuid,
parent_provider_uuid=parent_uuid),
resources=[],
)
summary.traits = prov_traits[rp_id]

View File

@@ -310,32 +310,17 @@ def provider_ids_from_rp_ids(context, rp_ids):
:param rp_ids: iterable of internal provider IDs to look up
"""
# SELECT
# rp.id, rp.uuid,
# parent.id AS parent_id, parent.uuid AS parent_uuid,
# root.id AS root_id, root.uuid AS root_uuid
# rp.id, rp.uuid, rp.parent_provider_id, rp.root_provider.id
# FROM resource_providers AS rp
# INNER JOIN resource_providers AS root
# ON rp.root_provider_id = root.id
# LEFT JOIN resource_providers AS parent
# ON rp.parent_provider_id = parent.id
# WHERE rp.id IN ($rp_ids)
me = sa.alias(_RP_TBL, name="me")
parent = sa.alias(_RP_TBL, name="parent")
root = sa.alias(_RP_TBL, name="root")
cols = [
me.c.id,
me.c.uuid,
parent.c.id.label('parent_id'),
parent.c.uuid.label('parent_uuid'),
root.c.id.label('root_id'),
root.c.uuid.label('root_uuid'),
me.c.parent_provider_id.label('parent_id'),
me.c.root_provider_id.label('root_id'),
]
me_to_root = sa.join(me, root, me.c.root_provider_id == root.c.id)
me_to_parent = sa.outerjoin(
me_to_root, parent,
me.c.parent_provider_id == parent.c.id)
sel = sa.select(cols).select_from(me_to_parent)
sel = sel.where(me.c.id.in_(sa.bindparam('rps', expanding=True)))
sel = sa.select(cols).where(me.c.id.in_(rp_ids))
ret = {}
for r in context.session.execute(sel, {'rps': list(rp_ids)}):