編集 :それで、私は以下のクエリを書いて、考えました...「ちょっと待ってください。Postgresqlでは外部キーターゲットに一意のインデックスが必要です。」だから私はあなたが何を意味するのか誤解したと思いますか?以下のクエリを使用して、ソースが 「confrelid」を「conrelid」に、「confkey」を「conkey」に置き換えることで、外部キーのインデックスが作成されます(ええ、ええ、クエリにエイリアスはありません...)
さて、システムカタログを調べることは可能だと思います...いつものように、システムカタログへの最良のガイドは、psqlを使用して「\ setECHO_HIDDEN 1」を実行し、それが興味深い「\」に対してどのSQLを生成するかを確認することです。 d"コマンド。テーブルの外部キー( "\ d tablename")を見つけるために使用されるSQLは次のとおりです:
-- $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
外部キーの場合はnull以外であるため、は外部テーブルの列番号です。また、これが外部キーを表示する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
unnest のような8.4の機能を使用します。 ...あなたはなしでうまくやっていくことができるかもしれません。
最終的に:
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, ' ')
OK、この怪物は候補インデックスコマンドを出力し、それらを既存のインデックスと一致させようとします。したがって、最後に「where indexrelid is null」を追加するだけで、存在しないように見えるインデックスを作成するコマンドを取得できます。
このクエリは、複数列の外部キーをうまく処理しません。しかし、それらを使用している場合は、問題が発生するに値します。
後の編集 :これは、提案された編集を上部に配置したクエリです。したがって、これは、外部キーのソース(ターゲットではない)である列に、存在しないインデックスを作成するコマンドを示しています。
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
私の経験では、これはそれほど有用ではありません。インデックスを作成する必要がない参照コードなどのインデックスを作成することをお勧めします。