EDIT: entonces, escribí la consulta a continuación y luego pensé ... "Espera, Postgresql requiere que los objetivos de claves extranjeras tengan índices únicos". ¿Entonces supongo que entendí mal lo que querías decir? Puede usar la consulta siguiente para verificar que la fuente de sus claves externas tenga índices al sustituir "conrelid" por "confrelid" y "conkey" por "confkey" (sí, sí, sin alias en la consulta ...)
Bueno, supongo que debería ser posible revisar los catálogos del sistema ... Como de costumbre, la mejor guía para los catálogos del sistema es usar psql y hacer "\ set ECHO_HIDDEN 1" y luego ver qué SQL genera para interesantes comandos "\ d". Aquí está el SQL que se utiliza para encontrar las claves foráneas de una tabla ("\ d nombre de tabla"):
-- $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;
Parece que pg_constraint tiene columnas conkey
y confkey
que parecen que podrían ser los números de las columnas que la clave se define a través de . Probablemente confkey
son los números de columna en la tabla foránea ya que solo no son nulos para claves externas. Además, me llevó un tiempo darme cuenta de que este es el SQL para mostrar las claves externas haciendo referencia a en la tabla dada. Que es lo que queremos de todos modos.
Así que algo esta consulta muestra los datos empezando a tomar forma:
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
Voy a utilizar 8.4 características como unnest ... que podría ser capaz de llevarse bien sin él.
que terminó con:
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, ' ')
bien, esta monstruosidad imprime los comandos de índice candidatos y trata de ellos coinciden con los índices existentes. Entonces, simplemente puede agregar "donde indexrelid es nulo" al final para que los comandos creen índices que no parecen existir.
Esta consulta no trata muy bien con claves externas de varias columnas; pero si estás usando eso, te mereces problemas. EDITAR
TARDE:. Aquí está la consulta con las modificaciones propuestas en la parte superior puesto en Así que esto muestra los comandos para crear índices que no existen, en las columnas que son la fuente de una clave externa (no su objetivo).
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
Mi experiencia es que esto no es realmente tan útil. Sugiere crear índices para cosas como códigos de referencia que realmente no necesitan ser indexados.
Después de su edición, esto parece que podría trabajar, voy a ejecutar una comparación entre esta y la respuesta de leonbloy – biggusjimmus
Este no muestra claves externas, solo claves primarias. No tiene sentido porque no necesita índice para pk porque la restricción pk "es" un índice –
@peperg no, la consulta no tiene nada que ver con las claves primarias directamente: encuentra el destino para las claves externas. por supuesto, si su base de datos está bien diseñada, los objetivos para claves externas son claves primarias. Observe la edición en la parte superior que sugiere cómo se podría cambiar para encontrar dónde no está indexada la * fuente * de una clave externa (que en realidad no es demasiado útil en mi humilde opinión). Perdón por la confusión, probablemente la respuesta deba ser reescrita. – araqnid