Postgres and Indexes on Foreign Keys and Primary Keys

前端 未结 7 1713
青春惊慌失措
青春惊慌失措 2020-12-02 03:34

Does Postgres automatically put indexes on Foreign Keys and Primary Keys? How can I tell? Is there a command that will return all indexes on a table?

7条回答
  •  佛祖请我去吃肉
    2020-12-02 04:13

    This function, based on the work by Laurenz Albe at https://www.cybertec-postgresql.com/en/index-your-foreign-key/, list all the foreign keys with missing indexes. The size of the table is shown, as for small tables the scanning performance could be superior to the index one.

    --
    -- function:    fkeys_missing_indexes
    -- purpose:     list all foreing keys in the database without and index in the source table.
    -- author:      Laurenz Albe
    -- see:         https://www.cybertec-postgresql.com/en/index-your-foreign-key/
    --
    create or replace function oftool_fkey_missing_indexes () 
    returns table (
      src_table     regclass,
      fk_columns    varchar,
      table_size    varchar,
      fk_constraint name,
      dst_table     regclass
    )
    as $$
    select
      -- source table having ta foreign key declaration
      tc.conrelid::regclass as src_table,
      
      -- ordered list of foreign key columns
      string_agg(ta.attname, ',' order by tx.n) as fk_columns,
      
      -- source table size
      pg_catalog.pg_size_pretty (
        pg_catalog.pg_relation_size(tc.conrelid)
      ) as table_size,
      
      -- name of the foreign key constraint
      tc.conname as fk_constraint,
      
      -- name of the target or destination table
      tc.confrelid::regclass as dst_table
      
    from pg_catalog.pg_constraint tc
    
    -- enumerated key column numbers per foreign key
    cross join lateral unnest(tc.conkey) with ordinality as tx(attnum, n)
    
    -- name for each key column
    join pg_catalog.pg_attribute ta on ta.attnum = tx.attnum and ta.attrelid = tc.conrelid
    
    where not exists (
      -- is there ta matching index for the constraint?
      select 1 from pg_catalog.pg_index i
      where 
        i.indrelid = tc.conrelid and 
        -- the first index columns must be the same as the key columns, but order doesn't matter
        (i.indkey::smallint[])[0:cardinality(tc.conkey)-1] @> tc.conkey) and 
        tc.contype = 'f'
      group by 
        tc.conrelid, 
        tc.conname, 
        tc.confrelid
      order by 
        pg_catalog.pg_relation_size(tc.conrelid) desc;
    $$ language sql;
    

    test it this way,

    select * from oftool_fkey_missing_indexes();
    

    you'll see a list like this.

    fk_columns            |table_size|fk_constraint                     |dst_table        |
    ----------------------|----------|----------------------------------|-----------------|
    id_group              |0 bytes   |fk_customer__group                |im_group         |
    id_product            |0 bytes   |fk_cart_item__product             |im_store_product |
    id_tax                |0 bytes   |fk_order_tax_resume__tax          |im_tax           |
    id_product            |0 bytes   |fk_order_item__product            |im_store_product |
    id_tax                |0 bytes   |fk_invoice_tax_resume__tax        |im_tax           |
    id_product            |0 bytes   |fk_invoice_item__product          |im_store_product |
    id_article,locale_code|0 bytes   |im_article_comment_id_article_fkey|im_article_locale|
    

提交回复
热议问题