SELECT pg_index.indexrelid::regclass, 'create index ' || relname || '_' ||
array_to_string(column_name_list, '_') || '_idx on ' || conrelid ||
' (' || array_to_string(column_name_list, ',') || ')'
FROM (SELECT DISTINCT
conrelid,
array_agg(attname) column_name_list,
array_agg(attnum) AS column_list
FROM pg_attribute
JOIN (SELECT conrelid::regclass,
conname,
unnest(conkey) AS column_index
FROM (SELECT DISTINCT
conrelid, conname, conkey
FROM pg_constraint
JOIN pg_class ON pg_class.oid = pg_constraint.conrelid
JOIN pg_namespace ON pg_namespace.oid = pg_class.relnamespace
WHERE nspname !~ '^pg_' AND nspname <> 'information_schema'
) fkey
) fkey
ON fkey.conrelid = pg_attribute.attrelid
AND fkey.column_index = pg_attribute.attnum
GROUP BY conrelid, conname
) candidate_index
JOIN pg_class ON pg_class.oid = candidate_index.conrelid
LEFT JOIN pg_index ON pg_index.indrelid = conrelid
AND indkey::text = array_to_string(column_list, ' ')
WHERE indexrelid IS NULL