sql >> データベース >  >> RDS >> PostgreSQL

PostgreSQL:すべての外部キーにインデックスを付ける方法は?

    編集 :それで、私は以下のクエリを書いて、考えました...「ちょっと待ってください。Postgresqlでは外部キーターゲットに一意のインデックスが必要です。」だから私はあなたが何を意味するのか誤解したと思いますか?以下のクエリを使用して、ソースが 「confrelid」を「conrelid」に、「confkey」を「conkey」に置き換えることで、外部キーのインデックスが作成されます(ええ、ええ、クエリにエイリアスはありません...)

    さて、システムカタログを調べることは可能だと思います...いつものように、システムカタログへの最良のガイドは、psqlを使用して「\ setECHO_HIDDEN 1」を実行し、それが興味深い「\」に対してどのSQLを生成するかを確認することです。 d"コマンド。テーブルの外部キー( "\ d tablename")を見つけるために使用されるSQLは次のとおりです:

    -- $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 外部キーの場合はnull以外であるため、は外部テーブルの列番号です。また、これが外部キーを表示する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
    

    unnest のような8.4の機能を使用します。 ...あなたはなしでうまくやっていくことができるかもしれません。

    最終的に:

    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、この怪物は候補インデックスコマンドを出力し、それらを既存のインデックスと一致させようとします。したがって、最後に「where indexrelid is null」を追加するだけで、存在しないように見えるインデックスを作成するコマンドを取得できます。

    このクエリは、複数列の外部キーをうまく処理しません。しかし、それらを使用している場合は、問題が発生するに値します。

    後の編集 :これは、提案された編集を上部に配置したクエリです。したがって、これは、外部キーのソース(ターゲットではない)である列に、存在しないインデックスを作成するコマンドを示しています。

    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. ImportError:MySQLdbという名前のモジュールがありません

    2. Postgresが配列にありません

    3. Linqがレコードの範囲を選択

    4. Oracle SQL Developerで変数を使用するにはどうすればよいですか?