perf: add LIMIT to unbounded DISTINCT ON, guard device table scan, add DB indexes
Bound batch DISTINCT ON queries by input count. Guard Repo.all(Devices) with exists? check. Add trigram GIN index on base_callsign and (has_weather, received_at DESC) partial index. Ultraworked with Sisyphus Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
parent
7f814462ed
commit
ff3a478bbd
4 changed files with 46 additions and 10 deletions
|
|
@ -228,17 +228,15 @@ defmodule Aprsme.DeviceIdentification do
|
|||
end
|
||||
|
||||
defp lookup_device_from_db(identifier) do
|
||||
# Fetch all device patterns from DB
|
||||
devices =
|
||||
try do
|
||||
Repo.all(Devices)
|
||||
rescue
|
||||
_ -> []
|
||||
end
|
||||
if Repo.exists?(from(d in Devices, limit: 1)) do
|
||||
devices = Repo.all(Devices)
|
||||
|
||||
Enum.find(devices, fn device ->
|
||||
pattern_matches?(device.identifier, identifier)
|
||||
end)
|
||||
Enum.find(devices, fn device ->
|
||||
pattern_matches?(device.identifier, identifier)
|
||||
end)
|
||||
end
|
||||
rescue
|
||||
_ -> nil
|
||||
end
|
||||
|
||||
defp pattern_matches?(pattern, identifier) do
|
||||
|
|
|
|||
|
|
@ -56,12 +56,14 @@ defmodule Aprsme.Packets.PreparedQueries do
|
|||
|
||||
def get_latest_packets_for_callsigns(callsigns) when is_list(callsigns) do
|
||||
normalized = Enum.map(callsigns, &String.upcase(String.trim(&1)))
|
||||
limit = length(callsigns)
|
||||
|
||||
Repo.all(
|
||||
from(p in Packet,
|
||||
where: fragment("upper(?)", p.sender) in ^normalized,
|
||||
distinct: fragment("upper(?)", p.sender),
|
||||
order_by: [asc: fragment("upper(?)", p.sender), desc: p.received_at],
|
||||
limit: ^limit,
|
||||
select: %{p | lat: fragment("ST_Y(?)", p.location), lon: fragment("ST_X(?)", p.location)}
|
||||
)
|
||||
)
|
||||
|
|
@ -77,6 +79,7 @@ defmodule Aprsme.Packets.PreparedQueries do
|
|||
|
||||
def get_latest_positions_for_callsigns(callsigns) when is_list(callsigns) do
|
||||
normalized = Enum.map(callsigns, &String.upcase(String.trim(&1)))
|
||||
limit = length(callsigns)
|
||||
|
||||
Repo.all(
|
||||
from(p in Packet,
|
||||
|
|
@ -84,6 +87,7 @@ defmodule Aprsme.Packets.PreparedQueries do
|
|||
where: not is_nil(p.location),
|
||||
distinct: fragment("upper(?)", p.sender),
|
||||
order_by: [asc: fragment("upper(?)", p.sender), desc: p.received_at],
|
||||
limit: ^limit,
|
||||
select: %{callsign: p.sender, lat: fragment("ST_Y(?)", p.location), lng: fragment("ST_X(?)", p.location)}
|
||||
)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
defmodule Aprsme.Repo.Migrations.AddBaseCallsignTrigramIndex do
|
||||
use Ecto.Migration
|
||||
@disable_ddl_transaction true
|
||||
@disable_migration_lock true
|
||||
|
||||
def up do
|
||||
execute """
|
||||
CREATE INDEX IF NOT EXISTS idx_packets_base_callsign_trgm
|
||||
ON packets USING gin (base_callsign gin_trgm_ops)
|
||||
WHERE base_callsign IS NOT NULL
|
||||
"""
|
||||
end
|
||||
|
||||
def down do
|
||||
execute "DROP INDEX IF EXISTS idx_packets_base_callsign_trgm"
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
defmodule Aprsme.Repo.Migrations.AddHasWeatherReceivedAtIndex do
|
||||
use Ecto.Migration
|
||||
@disable_ddl_transaction true
|
||||
@disable_migration_lock true
|
||||
|
||||
def up do
|
||||
execute """
|
||||
CREATE INDEX IF NOT EXISTS idx_packets_has_weather_time
|
||||
ON packets (has_weather, received_at DESC)
|
||||
WHERE has_weather = true
|
||||
"""
|
||||
end
|
||||
|
||||
def down do
|
||||
execute "DROP INDEX IF EXISTS idx_packets_has_weather_time"
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Reference in a new issue