aprs.me/priv/repo/migrations/20250730185642_optimize_packet_queries.exs
Graham McIntire d68f0f2e08
fix: Remove non-immutable NOW() function from index predicate
PostgreSQL requires functions in index predicates to be immutable.
The NOW() function is not immutable, so we simplify the index to
just order by received_at DESC without the WHERE clause.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-30 14:15:13 -05:00

77 lines
2.8 KiB
Elixir

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