2016-04-26 20 views
1

私はのためにOracle 12cと書いたクエリでパフォーマンスが非常に悪いです。おそらく私の非効率的な結合の使用に関係していて、誰かが私が間違っているところで私を助けてくれることを期待していました。私が持っている質問は現在を実行するのに1分以上かかるです。結合パフォーマンスの悪いSQLクエリ

私はどこのテーブル名とカラム名を返すようにしようとしていますよ:列が主キー

  • に属し

    • 列の型がテーブルの所有者がMY_OWNERある番号
    • です
    • 主キーが

    電流増幅率単一列制約であります具体的には次のようになります。

    SELECT consCols.table_name, consCols.column_name 
    FROM all_cons_columns consCols 
    INNER JOIN all_constraints cons 
        ON cons.constraint_name = consCols.constraint_name 
    INNER JOIN all_tab_columns cols 
        ON consCols.table_name = cols.table_name AND consCols.column_name = cols.column_name 
    WHERE cons.constraint_type = 'P' 
    AND cons.owner = 'MY_OWNER' 
    AND cols.data_type = 'NUMBER' 
    AND consCols.table_name IN(
        SELECT consCols2.table_name 
        FROM all_cons_columns consCols2 
        INNER JOIN all_constraints cons2 
        ON cons2.constraint_name = consCols2.constraint_name 
        WHERE cons2.constraint_type = 'P' 
        AND cons2.owner = 'MY_OWNER' 
        GROUP BY consCols2.table_name 
        HAVING COUNT(consCols2.table_name) = 1 
    ); 
    

    私に教えていただきありがとうございます。

  • +1

    クエリの実行計画を実行して結果を投稿してください。 – OldProgrammer

    答えて

    3

    分析関数を使用するとクエリが高速化されますか?

    SELECT table_name, column_name 
    FROM (SELECT consCols.table_name, consCols.column_name, cols.data_type, 
          COUNT(*) OVER (PARTITION BY consCols.table_name) as cnt 
         FROM all_cons_columns consCols INNER JOIN 
          all_constraints cons 
          ON cons.constraint_name = consCols.constraint_name INNER JOIN 
          all_tab_columns cols 
          ON consCols.table_name = cols.table_name AND consCols.column_name = cols.column_name 
         WHERE cons.constraint_type = 'P' AND 
          cons.owner = 'MY_OWNER' 
        ) tc    
    WHERE data_type = 'NUMBER' AND cnt = 1; 
    

    さらには集約?ここで

    SELECT consCols.table_name, consCols.column_name 
        FROM all_cons_columns consCols INNER JOIN 
         all_constraints cons 
         ON cons.constraint_name = consCols.constraint_name INNER JOIN 
         all_tab_columns cols 
         ON consCols.table_name = cols.table_name AND consCols.column_name = cols.column_name 
        WHERE cons.constraint_type = 'P' AND 
         cons.owner = 'MY_OWNER' 
        GROUP BY consCols.table_name, consCols.column_name 
        HAVING COUNT(*) = 1 AND 
         MAX(cols.data_type) = 'NUMBER'; 
    

    が第三の選択肢です:

    SELECT consCols.table_name, consCols.column_name 
        FROM all_cons_columns consCols INNER JOIN 
         all_constraints cons 
         ON cons.constraint_name = consCols.constraint_name INNER JOIN 
         all_tab_columns cols 
         ON consCols.table_name = cols.table_name AND consCols.column_name = cols.column_name 
        WHERE cons.constraint_type = 'P' AND 
         cons.owner = 'MY_OWNER' AND 
         cols.data_type = 'NUMBER' AND 
         NOT EXISTS (SELECT 1 
            FROM all_cons_columns acc 
            WHERE acc.constraint_name = consCols.constraint_name AND 
              acc.table_name = consCols.table_name AND 
              acc.column_name <> consCols.column_name 
            ); 
    

    これは凝集を排除し、ルックアップは、比較的高速である必要があります。

    +0

    ありがとう@Gordon。どちらの答えも約20秒かかるので勝ちです。私が5秒未満を望んでいた間、これはまだかなりの改善であり、私を大きく助けます。 – Venick

    +0

    ニースの回答。集計SQLに小さなエラーがあります - 最後から3行目のANDを削除してください。データ辞書のクエリは、10gから12cにアップグレードしてからかなり長い時間がかかることがわかりました。 –

    +0

    訂正、回答番号1は約20秒でうまくいきますが、回答2は実際には多すぎる行を返します。私は#1に固執することはできますが、それは問題ありません。 また、all_constraintsにcolumn_nameカラムがないので#3の答えは私には役に立たない:( – Venick

    関連する問題