defmodule Aprsme.Repo.Migrations.OptimizePacketQueries do use Ecto.Migration @disable_ddl_transaction true @disable_migration_lock true def up do # Index for path pattern matching (used in heard_by queries) # Using btree with text_pattern_ops for LIKE queries since trigram might not be available execute """ CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_packets_path_pattern ON packets(path text_pattern_ops) WHERE path IS NOT NULL AND path != '' """ # Composite index for base_callsign lookups with time execute """ CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_packets_base_callsign_time ON packets(base_callsign, received_at DESC) WHERE base_callsign IS NOT NULL """ # Index for device_identifier lookups execute """ CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_packets_device_identifier ON packets(device_identifier) WHERE device_identifier IS NOT NULL """ # Index for recent packets - using simple timestamp ordering # Note: We can't use NOW() in the WHERE clause as it's not immutable execute """ CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_packets_recent_only ON packets(received_at DESC) """ # Index for weather packet lookups by callsign execute """ CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_packets_weather_by_callsign ON packets(sender, received_at DESC) WHERE (temperature IS NOT NULL OR humidity IS NOT NULL OR pressure IS NOT NULL OR wind_speed IS NOT NULL OR wind_direction IS NOT NULL OR rain_1h IS NOT NULL) """ # Optimize existing indexes by updating statistics execute "ANALYZE packets" # Increase statistics target for frequently queried columns execute "ALTER TABLE packets ALTER COLUMN sender SET STATISTICS 1000" execute "ALTER TABLE packets ALTER COLUMN received_at SET STATISTICS 1000" execute "ALTER TABLE packets ALTER COLUMN base_callsign SET STATISTICS 500" # Create a compound index for the common "latest packet per callsign" query pattern execute """ CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_packets_sender_id_desc ON packets(sender, id DESC) """ end def down do execute "DROP INDEX IF EXISTS idx_packets_path_pattern" execute "DROP INDEX IF EXISTS idx_packets_base_callsign_time" execute "DROP INDEX IF EXISTS idx_packets_device_identifier" execute "DROP INDEX IF EXISTS idx_packets_recent_only" execute "DROP INDEX IF EXISTS idx_packets_weather_by_callsign" execute "DROP INDEX IF EXISTS idx_packets_sender_id_desc" # Reset statistics to default execute "ALTER TABLE packets ALTER COLUMN sender SET STATISTICS DEFAULT" execute "ALTER TABLE packets ALTER COLUMN received_at SET STATISTICS DEFAULT" execute "ALTER TABLE packets ALTER COLUMN base_callsign SET STATISTICS DEFAULT" end end