sql >> Databáze >  >> RDS >> PostgreSQL

PostgreSQL:Jak indexovat všechny cizí klíče?

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.



  1. Aplikace Laravel v Azure:Přístup odepřen uživateli 'azure'@'localhost'

  2. MySQL SELECT n záznamy založené na GROUP BY

  3. Jak mohu zobrazit, zda letecká společnost odlétá ze všech letišť v mé DB v Postgresql?

  4. řazení podle vysoké-nízké ceny s daty mysql