aprs.me/priv/repo/migrations/20250726225000_complete_optimized_indexes.exs
2025-07-26 18:41:08 -05:00

91 lines
2.6 KiB
Elixir

defmodule Aprsme.Repo.Migrations.CompleteOptimizedIndexes do
use Ecto.Migration
@disable_ddl_transaction true
@disable_migration_lock true
def up do
# Add has_weather column without GENERATED clause first
# We'll populate it with a trigger instead
execute """
ALTER TABLE packets
ADD COLUMN IF NOT EXISTS has_weather boolean DEFAULT false
"""
# Create trigger to maintain has_weather
execute """
CREATE OR REPLACE FUNCTION update_has_weather()
RETURNS TRIGGER AS $$
BEGIN
NEW.has_weather := (
NEW.temperature IS NOT NULL OR
NEW.humidity IS NOT NULL OR
NEW.pressure IS NOT NULL OR
NEW.wind_speed IS NOT NULL OR
NEW.wind_direction IS NOT NULL OR
NEW.rain_1h IS NOT NULL
);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
"""
execute """
DROP TRIGGER IF EXISTS update_has_weather_trigger ON packets;
"""
execute """
CREATE TRIGGER update_has_weather_trigger
BEFORE INSERT OR UPDATE ON packets
FOR EACH ROW
EXECUTE FUNCTION update_has_weather();
"""
# Update existing rows in batches to avoid timeout
execute """
UPDATE packets
SET has_weather = (
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
)
WHERE id IN (
SELECT id FROM packets
WHERE has_weather IS NULL
LIMIT 100000
);
"""
# Create remaining indexes
execute """
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_packets_has_weather
ON packets (has_weather, sender, received_at DESC)
WHERE has_weather = true
"""
execute """
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_packets_region_position_time
ON packets (region, has_position, received_at DESC)
WHERE has_position = true AND region IS NOT NULL
"""
execute """
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_packets_datatype_sender_time
ON packets (data_type, sender, received_at DESC)
"""
# Analyze the table to update statistics
execute "ANALYZE packets;"
end
def down do
execute "DROP INDEX IF EXISTS idx_packets_datatype_sender_time;"
execute "DROP INDEX IF EXISTS idx_packets_region_position_time;"
execute "DROP INDEX IF EXISTS idx_packets_has_weather;"
execute "DROP TRIGGER IF EXISTS update_has_weather_trigger ON packets;"
execute "DROP FUNCTION IF EXISTS update_has_weather();"
execute "ALTER TABLE packets DROP COLUMN IF EXISTS has_weather;"
end
end