Optimize equipment assignment breakdown N+1 query
Replaced application-level logic with single SQL query using CASE statement to determine assignment source directly in the database. Before: Loaded all equipment, called get_effective_agent_token_with_source for each (500 equipment = 500+ queries) After: Single query with CASE statement to classify assignment source Performance improvement: Reduces from O(n) queries to 1 query regardless of equipment count.
This commit is contained in:
parent
ae9983c4f6
commit
07debd98a7
1 changed files with 33 additions and 16 deletions
|
|
@ -91,25 +91,42 @@ defmodule Towerops.Agents.Stats do
|
|||
}
|
||||
"""
|
||||
def get_equipment_assignment_breakdown(organization_id) do
|
||||
# Get all equipment for organization
|
||||
equipment_query =
|
||||
from(e in Equipment,
|
||||
join: s in assoc(e, :site),
|
||||
where: s.organization_id == ^organization_id and e.snmp_enabled == true,
|
||||
preload: [:site, site: :organization]
|
||||
# Use a single SQL query with CASE to determine assignment source
|
||||
# This avoids loading all equipment into memory and calling get_effective_agent_token_with_source
|
||||
results =
|
||||
Repo.all(
|
||||
from(e in Equipment,
|
||||
join: s in assoc(e, :site),
|
||||
join: o in assoc(s, :organization),
|
||||
left_join: aa in AgentAssignment,
|
||||
on: aa.equipment_id == e.id and aa.enabled == true,
|
||||
where: s.organization_id == ^organization_id and e.snmp_enabled == true,
|
||||
select: %{
|
||||
source:
|
||||
fragment(
|
||||
"""
|
||||
CASE
|
||||
WHEN ? IS NOT NULL THEN 'equipment'
|
||||
WHEN ? IS NOT NULL THEN 'site'
|
||||
WHEN ? IS NOT NULL THEN 'organization'
|
||||
ELSE 'cloud'
|
||||
END
|
||||
""",
|
||||
aa.agent_token_id,
|
||||
s.agent_token_id,
|
||||
o.default_agent_token_id
|
||||
)
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
equipment_list = Repo.all(equipment_query)
|
||||
|
||||
# Count by assignment type
|
||||
Enum.reduce(equipment_list, %{direct: 0, site: 0, organization: 0, cloud: 0}, fn eq, acc ->
|
||||
{_agent_id, source} = Towerops.Agents.get_effective_agent_token_with_source(eq)
|
||||
|
||||
# Count by assignment source
|
||||
Enum.reduce(results, %{direct: 0, site: 0, organization: 0, cloud: 0}, fn %{source: source}, acc ->
|
||||
case source do
|
||||
:equipment -> %{acc | direct: acc.direct + 1}
|
||||
:site -> %{acc | site: acc.site + 1}
|
||||
:organization -> %{acc | organization: acc.organization + 1}
|
||||
:none -> %{acc | cloud: acc.cloud + 1}
|
||||
"equipment" -> %{acc | direct: acc.direct + 1}
|
||||
"site" -> %{acc | site: acc.site + 1}
|
||||
"organization" -> %{acc | organization: acc.organization + 1}
|
||||
"cloud" -> %{acc | cloud: acc.cloud + 1}
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue