PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

PostgreSQL:Как да индексирам всички външни ключове?

РЕДАКТИРАНЕ :така, написах заявката по-долу и след това си помислих... "чакай, Postgresql изисква целевите външни ключове да имат уникални индекси." Така че предполагам, че не съм разбрал какво имаш предвид? Можете да използвате заявката по-долу, за да проверите дали източникът от вашите външни ключове имат индекси, като замените "conrelid" с "confrelid" и "conkey" с "confkey" (да, да, няма псевдоними в заявката...)

Е, предполагам, че трябва да е възможно да преминете през системните каталози... Както обикновено, най-доброто ръководство за системните каталози е да използвате psql и да направите "\set ECHO_HIDDEN 1" и след това да видите какъв SQL генерира за интересни "\ d" команди. Ето SQL, използван за намиране на външни ключове за таблица ("\d име на таблица"):

-- $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;

Изглежда, че pg_constraint има колони conkey и confkey които изглеждат така, сякаш може да са номерата на колоните, в които е дефиниран ключът. Вероятно confkey е номерата на колоните във външната таблица, тъй като не е нула само за външни ключове. Освен това ми отне известно време, за да разбера, че това е SQL за показване на рефериране на външни ключове дадената таблица. Което така или иначе искаме.

Така че нещо, което тази заявка показва, че данните започват да се оформят:

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

Ще използвам 8.4 функции като unnest ... може да успеете да се справите без него.

В крайна сметка получих:

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, ' ')

Добре, това чудовище отпечатва командите на кандидат индекса и се опитва да ги съпостави със съществуващите индекси. Така че можете просто да добавите „където indexrelid е null“ в края, за да получите командите за създаване на индекси, които изглежда не съществуват.

Тази заявка не се справя много добре с многоколонни външни ключове; но imho, ако ги използвате, заслужавате проблеми.

ПО-КЪСНО РЕДАКТИРАНЕ :ето заявката с предложените редакции в горната част. Така че това показва командите за създаване на индекси, които не съществуват, в колони, които са източник на чужд ключ (а не негова цел).

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

Моят опит показва, че това всъщност не е толкова полезно. Предлага създаване на индекси за неща като референтни кодове, които наистина не се нуждаят от индексиране.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. как да премахнете всички бази данни с изключение на няколко в postgres

  2. Вземете първия ден от месеца в PostgreSQL

  3. Как да разберете кога таблица на Postgres е била групирана и какви индекси са използвани

  4. Обединяване на връзки към база данни на Celery Worker

  5. Как Atan() работи в PostgreSQL