РЕДАКТИРОВАТЬ : поэтому я написал запрос ниже, а затем подумал ... "Подожди, Postgresql требует, чтобы цели внешнего ключа имели уникальные индексы". Так что, наверное, я неправильно понял, что вы имели в виду? Вы можете использовать приведенный ниже запрос, чтобы проверить, имеют ли исходные ваших внешних ключей индексы, заменив «conrelid» на «confrelid» и «conkey» на «confkey» (да, да, в запросе нет псевдонимов ...)
Ну, я думаю, что должно быть возможно просмотреть системные каталоги ... Как обычно, лучшим руководством по системным каталогам является использование psql и выполнение "\ set ECHO_HIDDEN 1", а затем посмотреть, какой SQL он генерирует для интересные команды "\ d". Вот SQL, используемый для поиска внешних ключей для таблицы ("\ d имя_таблицы"):
-- $1 is the table OID, e.g. 'tablename'::regclass
SELECT conname, conrelid::pg_catalog.regclass,
pg_catalog.pg_get_constraintdef(c.oid, true) as condef
FROM pg_catalog.pg_constraint c
WHERE c.confrelid = $1 AND c.contype = 'f' ORDER BY 1;
Кажется, что pg_constraint имеет столбцы conkey
и confkey
, которые выглядят так, как будто они могут быть номерами столбцов, по которым определен ключ. Вероятно, confkey
- это номера столбцов во внешней таблице, поскольку для внешних ключей он не равен нулю. Кроме того, мне потребовалось некоторое время, чтобы понять, что это SQL для отображения внешних ключей , ссылающихся на данной таблицы. Что в любом случае мы хотим.
Итак, этот запрос показывает, что данные начинают обретать форму:
select confrelid, conname, column_index, attname
from pg_attribute
join (select confrelid::regclass, conname, unnest(confkey) as column_index
from pg_constraint
where confrelid = 'ticket_status'::regclass) fkey
on fkey.confrelid = pg_attribute.attrelid
and fkey.column_index = pg_attribute.attnum
Я собираюсь использовать 8.4 функций, таких как unnest ... вы можете обойтись без.
Я закончил с:
select pg_index.indexrelid::regclass, 'create index ' || relname || '_' ||
array_to_string(column_name_list, '_') || '_idx on ' || confrelid ||
' (' || array_to_string(column_name_list, ',') || ')'
from (select distinct
confrelid,
array_agg(attname) column_name_list,
array_agg(attnum) as column_list
from pg_attribute
join (select confrelid::regclass,
conname,
unnest(confkey) as column_index
from (select distinct
confrelid, conname, confkey
from pg_constraint
join pg_class on pg_class.oid = pg_constraint.confrelid
join pg_namespace on pg_namespace.oid = pg_class.relnamespace
where nspname !~ '^pg_' and nspname <> 'information_schema'
) fkey
) fkey
on fkey.confrelid = pg_attribute.attrelid
and fkey.column_index = pg_attribute.attnum
group by confrelid, conname
) candidate_index
join pg_class on pg_class.oid = candidate_index.confrelid
left join pg_index on pg_index.indrelid = confrelid
and indkey::text = array_to_string(column_list, ' ')
ОК, это чудовище печатает команды-кандидаты в индексы и пытается сопоставить их с существующими индексами. Таким образом, вы можете просто добавить «где indexrelid равен нулю» в конце, чтобы получить команды для создания индексов, которые, кажется, не существуют.
Этот запрос не очень хорошо работает с внешними ключами из нескольких столбцов; но imho, если вы используете их, вы заслуживаете неприятностей.
ПОСЛЕДНЕЕ РЕДАКТИРОВАНИЕ : вот запрос с предложенными правками вверху. Таким образом, показаны команды для создания несуществующих индексов для столбцов, являющихся источником внешнего ключа. (не его цель).
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
По моему опыту, это не так уж и полезно. Он предлагает создать индексы для таких вещей, как ссылочные коды, которые действительно не нужно индексировать.