Postgres วางดัชนีในคีย์ต่างประเทศและคีย์หลักโดยอัตโนมัติหรือไม่ ฉันจะบอกได้อย่างไร มีคำสั่งที่จะส่งคืนดัชนีทั้งหมดบนตารางหรือไม่?
Postgres วางดัชนีในคีย์ต่างประเทศและคีย์หลักโดยอัตโนมัติหรือไม่ ฉันจะบอกได้อย่างไร มีคำสั่งที่จะส่งคืนดัชนีทั้งหมดบนตารางหรือไม่?
คำตอบ:
PostgreSQL สร้างดัชนีโดยอัตโนมัติในคีย์หลักและข้อ จำกัด ที่ไม่ซ้ำกัน แต่ไม่ได้อยู่ในด้านการอ้างอิงของความสัมพันธ์กับคีย์ต่างประเทศ
เมื่อ Pg สร้างดัชนีโดยนัยมันจะNOTICE
ส่งข้อความระดับที่คุณสามารถเห็นในpsql
และ / หรือบันทึกของระบบเพื่อให้คุณสามารถเห็นเมื่อมันเกิดขึ้น ดัชนีที่สร้างขึ้นโดยอัตโนมัติจะปรากฏใน\d
เอาต์พุตสำหรับตารางด้วย
เอกสารเกี่ยวกับการจัดทำดัชนีที่ไม่ซ้ำกันพูดว่า:
PostgreSQL สร้างดัชนีโดยอัตโนมัติสำหรับข้อ จำกัด ที่ไม่ซ้ำกันและข้อ จำกัด ของคีย์หลักเพื่อบังคับใช้เอกลักษณ์ ดังนั้นจึงไม่จำเป็นต้องสร้างดัชนีอย่างชัดเจนสำหรับคอลัมน์คีย์หลัก
และเอกสารเกี่ยวกับข้อ จำกัดบอกว่า:
เนื่องจากการลบแถวจากตารางอ้างอิงหรือ UPDATE ของคอลัมน์อ้างอิงจะต้องมีการสแกนตารางอ้างอิงสำหรับแถวที่ตรงกับค่าเก่าดังนั้นจึงเป็นความคิดที่ดีที่จะสร้างดัชนีคอลัมน์อ้างอิง เนื่องจากสิ่งนี้ไม่จำเป็นเสมอไปและมีหลายทางเลือกในการจัดทำดัชนีการประกาศข้อ จำกัด คีย์ต่างประเทศจึงไม่สร้างดัชนีในคอลัมน์อ้างอิงโดยอัตโนมัติ
ดังนั้นคุณต้องสร้างดัชนีของคีย์ต่างประเทศด้วยตัวเองหากคุณต้องการ
โปรดทราบว่าหากคุณใช้คีย์หลักต่างประเทศเช่น 2 FK ในฐานะ PK ในตาราง M-to-N คุณจะมีดัชนีบน PK และอาจไม่จำเป็นต้องสร้างดัชนีพิเศษใด ๆ
แม้ว่าโดยทั่วไปแล้วคุณควรสร้างดัชนีใน (หรือรวมถึง) คอลัมน์คีย์ต่างประเทศอ้างอิงของคุณ แต่ก็ไม่จำเป็น แต่ละดัชนีคุณเพิ่มช้า DML การดำเนินงานลดลงเล็กน้อยเพื่อให้คุณจ่ายค่าใช้จ่ายการปฏิบัติงานในทุกINSERT
, หรือUPDATE
DELETE
หากดัชนีนั้นไม่ค่อยได้ใช้อาจไม่คุ้มค่า
หากคุณต้องการแสดงรายการดัชนีของตารางทั้งหมดในสคีมาของคุณจากโปรแกรมของคุณข้อมูลทั้งหมดอยู่ในมือในแคตตาล็อก:
select
n.nspname as "Schema"
,t.relname as "Table"
,c.relname as "Index"
from
pg_catalog.pg_class c
join pg_catalog.pg_namespace n on n.oid = c.relnamespace
join pg_catalog.pg_index i on i.indexrelid = c.oid
join pg_catalog.pg_class t on i.indrelid = t.oid
where
c.relkind = 'i'
and n.nspname not in ('pg_catalog', 'pg_toast')
and pg_catalog.pg_table_is_visible(c.oid)
order by
n.nspname
,t.relname
,c.relname
หากคุณต้องการเจาะลึกเพิ่มเติม (เช่นคอลัมน์และการสั่งซื้อ) คุณต้องดูที่ pg_catalog.pg_index การใช้psql -E [dbname]
มีประโยชน์สำหรับการค้นหาวิธีสืบค้นแคตตาล็อก
\di
จะแสดงรายการดัชนีทั้งหมดในฐานข้อมูลด้วย" (ความคิดเห็นที่คัดลอกมาจากคำตอบอื่น ๆ ใช้ที่นี่เช่นกัน)
แบบสอบถามนี้จะแสดงรายการดัชนีในคีย์ต่างประเทศหายไป , ต้นฉบับเดิม
แก้ไข : โปรดทราบว่าจะไม่ตรวจสอบตารางขนาดเล็ก (น้อยกว่า 9 MB) และกรณีอื่น ๆ ดูWHERE
คำสั่งสุดท้าย
-- check for FKs where there is no matching index
-- on the referencing side
-- or a bad index
WITH fk_actions ( code, action ) AS (
VALUES ( 'a', 'error' ),
( 'r', 'restrict' ),
( 'c', 'cascade' ),
( 'n', 'set null' ),
( 'd', 'set default' )
),
fk_list AS (
SELECT pg_constraint.oid as fkoid, conrelid, confrelid as parentid,
conname, relname, nspname,
fk_actions_update.action as update_action,
fk_actions_delete.action as delete_action,
conkey as key_cols
FROM pg_constraint
JOIN pg_class ON conrelid = pg_class.oid
JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid
JOIN fk_actions AS fk_actions_update ON confupdtype = fk_actions_update.code
JOIN fk_actions AS fk_actions_delete ON confdeltype = fk_actions_delete.code
WHERE contype = 'f'
),
fk_attributes AS (
SELECT fkoid, conrelid, attname, attnum
FROM fk_list
JOIN pg_attribute
ON conrelid = attrelid
AND attnum = ANY( key_cols )
ORDER BY fkoid, attnum
),
fk_cols_list AS (
SELECT fkoid, array_agg(attname) as cols_list
FROM fk_attributes
GROUP BY fkoid
),
index_list AS (
SELECT indexrelid as indexid,
pg_class.relname as indexname,
indrelid,
indkey,
indpred is not null as has_predicate,
pg_get_indexdef(indexrelid) as indexdef
FROM pg_index
JOIN pg_class ON indexrelid = pg_class.oid
WHERE indisvalid
),
fk_index_match AS (
SELECT fk_list.*,
indexid,
indexname,
indkey::int[] as indexatts,
has_predicate,
indexdef,
array_length(key_cols, 1) as fk_colcount,
array_length(indkey,1) as index_colcount,
round(pg_relation_size(conrelid)/(1024^2)::numeric) as table_mb,
cols_list
FROM fk_list
JOIN fk_cols_list USING (fkoid)
LEFT OUTER JOIN index_list
ON conrelid = indrelid
AND (indkey::int2[])[0:(array_length(key_cols,1) -1)] @> key_cols
),
fk_perfect_match AS (
SELECT fkoid
FROM fk_index_match
WHERE (index_colcount - 1) <= fk_colcount
AND NOT has_predicate
AND indexdef LIKE '%USING btree%'
),
fk_index_check AS (
SELECT 'no index' as issue, *, 1 as issue_sort
FROM fk_index_match
WHERE indexid IS NULL
UNION ALL
SELECT 'questionable index' as issue, *, 2
FROM fk_index_match
WHERE indexid IS NOT NULL
AND fkoid NOT IN (
SELECT fkoid
FROM fk_perfect_match)
),
parent_table_stats AS (
SELECT fkoid, tabstats.relname as parent_name,
(n_tup_ins + n_tup_upd + n_tup_del + n_tup_hot_upd) as parent_writes,
round(pg_relation_size(parentid)/(1024^2)::numeric) as parent_mb
FROM pg_stat_user_tables AS tabstats
JOIN fk_list
ON relid = parentid
),
fk_table_stats AS (
SELECT fkoid,
(n_tup_ins + n_tup_upd + n_tup_del + n_tup_hot_upd) as writes,
seq_scan as table_scans
FROM pg_stat_user_tables AS tabstats
JOIN fk_list
ON relid = conrelid
)
SELECT nspname as schema_name,
relname as table_name,
conname as fk_name,
issue,
table_mb,
writes,
table_scans,
parent_name,
parent_mb,
parent_writes,
cols_list,
indexdef
FROM fk_index_check
JOIN parent_table_stats USING (fkoid)
JOIN fk_table_stats USING (fkoid)
WHERE table_mb > 9
AND ( writes > 1000
OR parent_writes > 1000
OR parent_mb > 10 )
ORDER BY issue_sort, table_mb DESC, table_name, fk_name;
where
ข้อ: ท่ามกลางคนอื่น ๆ มันจะพิจารณาเฉพาะตารางที่มีขนาดมากกว่า 9 MB
ฉันชอบวิธีที่อธิบายไว้ในบทความคุณสมบัติการทำงานที่ยอดเยี่ยมของ EclipseLink 2.5
การทำดัชนีคีย์ต่างประเทศ
คุณสมบัติแรกคือการสร้างดัชนีอัตโนมัติของปุ่มต่างประเทศ คนส่วนใหญ่คิดว่าฐานข้อมูลคีย์ต่างประเทศผิดค่าเริ่มต้น พวกเขาทำไม่ได้ คีย์หลักถูกทำดัชนีโดยอัตโนมัติ แต่รหัสต่างประเทศไม่ใช่ ซึ่งหมายความว่าแบบสอบถามใด ๆ ที่ขึ้นอยู่กับ foreign key จะทำการสแกนแบบเต็มตาราง นี่คือใดOneToMany , ManyToManyหรือElementCollectionความสัมพันธ์เช่นเดียวกับหลาย OneToOne ความสัมพันธ์และแบบสอบถามมากที่สุดในความสัมพันธ์ใด ๆ ที่เกี่ยวข้องกับการเข้าร่วมหรือการเปรียบเทียบวัตถุ นี่อาจเป็นปัญหาการปฏิบัติที่สำคัญและคุณควรทำดัชนีเขตข้อมูลคีย์ต่างประเทศของคุณเสมอ
สำหรับ a PRIMARY KEY
ดัชนีจะถูกสร้างขึ้นด้วยข้อความต่อไปนี้:
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "index" for table "table"
สำหรับFOREIGN KEY
ข้อ จำกัด จะไม่ถูกสร้างขึ้นถ้ามีดัชนีใน referenc ไม่มีเอ็ดตาราง
ดัชนีใน referenc ไอเอ็นจีตารางไม่จำเป็นต้องใช้ ( แต่ต้องการ) และดังนั้นจึงจะไม่ถูกสร้างขึ้นโดยปริยาย