PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

PostgreSQL:Bagaimana cara mengindeks semua kunci asing?

EDIT :jadi, saya menulis kueri di bawah dan kemudian berpikir... "tunggu dulu, Postgresql mengharuskan target kunci asing harus memiliki indeks unik." Jadi saya kira saya salah mengerti apa yang Anda maksud? Anda dapat menggunakan kueri di bawah ini untuk memeriksa apakah sumber kunci asing Anda memiliki indeks dengan mengganti "conrelid" untuk "confrelid" dan "conkey" untuk "confkey" (ya, ya, tidak ada alias dalam kueri...)

Yah, saya rasa mungkin untuk menelusuri katalog sistem... Seperti biasa, panduan terbaik untuk katalog sistem adalah menggunakan psql dan melakukan "\set ECHO_HIDDEN 1" dan kemudian melihat SQL apa yang dihasilkannya untuk "\ d" perintah. Berikut SQL yang digunakan untuk menemukan kunci asing untuk sebuah tabel ("\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;

Tampaknya pg_constraint memiliki kolom conkey dan confkey yang terlihat seperti nomor kolom tempat kunci didefinisikan. Mungkin confkey adalah nomor kolom dalam tabel asing karena hanya non-null untuk kunci asing. Juga, butuh beberapa saat untuk menyadari bahwa ini adalah SQL untuk menunjukkan kunci asing referensi tabel yang diberikan. Itulah yang kami inginkan.

Jadi sesuatu yang ditunjukkan oleh kueri ini adalah data yang mulai terbentuk:

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

Saya akan menggunakan fitur 8.4 seperti unnest ... Anda mungkin bisa bergaul tanpanya.

Saya berakhir dengan:

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

Oke, monster ini mencetak perintah indeks kandidat dan mencoba mencocokkannya dengan indeks yang ada. Jadi Anda cukup menambahkan "where indexrelid is null" di bagian akhir untuk mendapatkan perintah untuk membuat indeks yang tampaknya tidak ada.

Kueri ini tidak menangani kunci asing multi-kolom dengan baik; tetapi jika Anda menggunakan itu, Anda layak mendapat masalah.

KEMUDIAN EDIT :ini query dengan usulan suntingan di atas. Jadi ini menunjukkan perintah untuk membuat indeks yang tidak ada, pada kolom yang merupakan sumber dari foreign key (bukan targetnya).

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

Pengalaman saya adalah bahwa ini tidak terlalu berguna. Ini menyarankan membuat indeks untuk hal-hal seperti kode referensi yang benar-benar tidak perlu diindeks.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Apakah mungkin untuk menjawab pertanyaan pada tampilan sebelum sepenuhnya mewujudkan tampilan?

  2. Bagaimana search_path mempengaruhi resolusi pengenal dan skema saat ini?

  3. Nama tabel dinamis di postgreSQL 9.3

  4. Bagaimana saya bisa memberi tahu PostgreSQL untuk tidak membatalkan seluruh transaksi ketika satu kendala gagal?

  5. PGError:tidak ada koneksi ke server setelah idle