CHỈNH SỬA :vì vậy, tôi đã viết truy vấn dưới đây và sau đó nghĩ rằng ... "chờ đã, Postgresql yêu cầu các mục tiêu khóa ngoài phải có các chỉ số duy nhất." Vì vậy, tôi đoán tôi đã hiểu sai ý của bạn? Bạn có thể sử dụng truy vấn bên dưới để kiểm tra xem nguồn trong số các khóa ngoại của bạn có các chỉ mục bằng cách thay thế "conrelid" cho "confrelid" và "conkey" cho "confkey" (vâng, vâng, không có bí danh trong truy vấn ...)
Chà, tôi đoán có thể xem qua danh mục hệ thống ... Như thường lệ, hướng dẫn tốt nhất về danh mục hệ thống là sử dụng psql và thực hiện "\ set ECHO_HIDDEN 1", sau đó xem SQL mà nó tạo ra có gì thú vị "\ lệnh d ”. Đây là SQL được sử dụng để tìm khóa ngoại cho một bảng ("\ d tablename"):
-- $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;
Có vẻ như pg_constraint có các cột conkey
và confkey
trông giống như chúng có thể là số cột mà khóa được xác định trên đó. Có thể là confkey
là số cột trong bảng ngoại vì nó chỉ khác rỗng đối với khóa ngoại. Ngoài ra, tôi phải mất một lúc để nhận ra đây là SQL để hiển thị khóa ngoại tham chiếu bảng đã cho. Đó là những gì chúng tôi muốn.
Vì vậy, một cái gì đó truy vấn này cho thấy dữ liệu bắt đầu hình thành:
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
Tôi sẽ sử dụng 8.4 tính năng như unnest ... bạn có thể hòa nhập mà không cần.
Tôi đã kết thúc với:
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, sự quái dị này in ra các lệnh chỉ mục ứng viên và cố gắng khớp chúng với các chỉ số hiện có. Vì vậy, bạn có thể chỉ cần thêm "nơi indexrelid là null" ở cuối để nhận các lệnh tạo chỉ số dường như không tồn tại.
Truy vấn này không xử lý tốt các khóa ngoại nhiều cột; nhưng imho nếu bạn đang sử dụng những thứ đó, bạn xứng đáng gặp rắc rối.
CHỈNH SỬA SAU :đây là truy vấn với các chỉnh sửa được đề xuất ở trên cùng được đưa vào. Vì vậy, điều này hiển thị các lệnh để tạo các chỉ mục không tồn tại, trên các cột là nguồn của khóa ngoại (không phải mục tiêu của nó).
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
Kinh nghiệm của tôi là điều này không thực sự hữu ích. Nó gợi ý tạo chỉ số cho những thứ như mã tham chiếu thực sự không cần lập chỉ mục.