BEARBEITEN :Also, ich habe die Abfrage unten geschrieben und dann gedacht ... "Moment mal, Postgresql erfordert, dass Fremdschlüsselziele eindeutige Indizes haben müssen." Also habe ich wohl falsch verstanden, was du meinst? Sie können die folgende Abfrage verwenden, um zu überprüfen, ob die Quelle Ihrer Fremdschlüssel haben Indizes, indem Sie "confrelid" durch "conrelid" und "confkey" durch "conkey" ersetzen (ja, ja, keine Aliase in der Abfrage ...)
Nun, ich schätze, es sollte möglich sein, die Systemkataloge zu durchsuchen ... Wie üblich ist die beste Anleitung zu den Systemkatalogen, psql zu verwenden und "\set ECHO_HIDDEN 1" auszuführen und dann zu sehen, welches SQL es für interessante "\ d" Befehle. Hier ist die SQL, die verwendet wird, um die Fremdschlüssel für eine Tabelle ("\d Tabellenname") zu finden:
-- $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;
Scheint, dass pg_constraint Spalten conkey
hat und confkey
die so aussehen, als könnten sie die Spaltennummern sein, über die der Schlüssel definiert ist. Wahrscheinlich confkey
ist die Spaltennummer in der Fremdtabelle, da sie nur für Fremdschlüssel ungleich Null ist. Außerdem brauchte ich eine Weile, um zu erkennen, dass dies die SQL ist, um Fremdschlüssel Referenzen anzuzeigen die angegebene Tabelle. Was wir sowieso wollen.
Diese Abfrage zeigt also, dass die Daten Gestalt annehmen:
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
Ich werde 8.4-Funktionen wie unnest verwenden ... kommen Sie vielleicht auch ohne aus.
Ich endete mit:
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, diese Monstrosität druckt die Kandidatenindexbefehle aus und versucht, sie mit bestehenden Indizes abzugleichen. Sie können also einfach "where indexrelid is null" am Ende hinzufügen, um die Befehle zum Erstellen von Indizes zu erhalten, die scheinbar nicht existieren.
Diese Abfrage geht nicht sehr gut mit mehrspaltigen Fremdschlüsseln um; aber imho, wenn Sie diese verwenden, verdienen Sie Ärger.
SPÄTERE BEARBEITUNG :Hier ist die Abfrage mit den vorgeschlagenen Änderungen ganz oben eingefügt. Dies zeigt also die Befehle zum Erstellen von Indizes, die nicht existieren, für Spalten, die die Quelle eines Fremdschlüssels (nicht sein Ziel) sind.
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
Meine Erfahrung ist, dass das nicht wirklich sinnvoll ist. Es schlägt vor, Indizes für Dinge wie Referenzcodes zu erstellen, die wirklich nicht indiziert werden müssen.