UPRAVIT :tak jsem napsal dotaz níže a pak jsem si pomyslel... "počkejte, Postgresql vyžaduje, aby cíle cizích klíčů měly jedinečné indexy." Takže jsem asi špatně pochopil, co jsi tím myslel? Pomocí níže uvedeného dotazu můžete zkontrolovat, zda je zdroj z vašich cizích klíčů mají indexy nahrazením "conrelid" za "confrelid" a "conkey" za "confkey" (ano, ano, v dotazu nejsou žádné aliasy...)
No, asi by se mělo dát projít systémové katalogy... Jako obvykle je nejlepším průvodcem systémovými katalogy použít psql a udělat "\set ECHO_HIDDEN 1" a pak se podívat, jaké SQL to vygeneruje za zajímavé "\ d" příkazy. Zde je SQL používaný k nalezení cizích klíčů pro tabulku ("\d název_tabulky"):
-- $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;
Zdá se, že pg_constraint má sloupce conkey
a confkey
které vypadají, že by to mohla být čísla sloupců, ve kterých je klíč definován. Pravděpodobně confkey
je čísla sloupců v cizí tabulce, protože je pouze nenulová pro cizí klíče. Chvíli mi také trvalo, než jsem si uvědomil, že toto je SQL pro zobrazení odkazování cizích klíčů danou tabulku. Což stejně chceme.
Takže něco, co tento dotaz ukazuje, jak se data začínají formovat:
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
Budu používat funkce 8.4, jako je unnest ... možná se bez toho obejdete.
Skončil jsem u:
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, tato zrůdnost vytiskne kandidátní indexové příkazy a pokusí se je porovnat s existujícími indexy. Takže můžete jednoduše přidat "kde indexrelid je null" na konec, abyste získali příkazy k vytvoření indexů, které se zdají neexistující.
Tento dotaz si s vícesloupcovými cizími klíči příliš neporadí; ale imho, pokud je používáte, zasloužíte si potíže.
POZDĚJŠÍ ÚPRAVY :zde je dotaz s navrhovanými úpravami umístěnými nahoře. Takže toto ukazuje příkazy k vytvoření indexů, které neexistují, ve sloupcích, které jsou zdrojem cizího klíče (ne jeho cíle).
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
Moje zkušenost je, že to není až tak užitečné. Navrhuje vytvářet indexy pro věci, jako jsou referenční kódy, které opravdu není nutné indexovat.