2

大量の JOIN 句を使用して大きなクエリを作成する方法を理解しようとしています。このクエリのパフォーマンスは同じですか?

/*Sql 1*/
SELECT G.ID, T1.QUANTITY, T2.QUANTITY
 FROM GOODS G
LEFT JOIN
/*First subquery*/
(SELECT SUM(QUANTITY) QUANTITY, GOOD_ID
FROM MY_TABLE_1
GROUP BY GOOD_ID
) T1 ON G.ID = T1.GOOD_ID
LEFT JOIN
/*Second subquery*/
(SELECT SUM(QUANTITY) QUANTITY, GOOD_ID
GROUP BY GOOD_ID
FROM MY_TABLE_2
) T2 ON G.ID = T2.GOOD_ID
/*and so on....Next same subqueries*/
WHERE G.ID IN (1, 2, 3, 4);

次のクエリでは、すべての結合サブクエリと LEFT JOIN 句の外側に設定された同じ WHERE 句が INNER CLAUSE で置き換えられます。それは良い解決策ですか?または、オラクルオプティマイザーは自動的にそのようなことを行いますか?

/*Sql 2*/
SELECT G.ID, T1.QUANTITY, T2.QUANTITY
 FROM GOODS G
INNER JOIN
/*First subquery*/
(SELECT SUM(QUANTITY) QUANTITY, GOOD_ID
FROM GOODS G
LEFT JOIN MY_TABLE_1 M ON M.GOOD_ID = G.ID
WHERE G.ID IN (1, 2, 3, 4);
GROUP BY GOOD_ID
) T1 ON G.ID = T1.GOOD_ID
INNER JOIN
/*Second subquery*/
(SELECT SUM(QUANTITY) QUANTITY, GOOD_ID
FROM GOODS G
LEFT JOIN MY_TABLE_2 M ON M.GOOD_ID = G.ID
WHERE G.ID IN (1, 2, 3, 4);
GROUP BY GOOD_ID
) T2 ON G.ID = T2.GOOD_ID
/*and so on....Next same subqueries*/
WHERE G.ID IN (1, 2, 3, 4);
4

3 に答える 3

2

クエリのパフォーマンスは、次のような多くの要素に依存します。

  • 関連するテーブルの相対的なサイズ
  • 結合列とフィルター条件をカバーするインデックスの有無
  • データベース内のテーブル統計の通貨
  • クエリの記述方法。

OUTER結合が INNER 結合よりも高速であるというのは、絶対に正しくありません (ただし、それが正しいクエリもあるかもしれません)。そのため、その理論に基づいてより多くの OUTER 結合を使用するようにクエリを変換しようとしても、時間の無駄です。

パフォーマンスの最適化に関する本全体が書かれていますが、いくつかの一般的なルールには以下が含まれます。

  • クエリでは、テーブルの結合と WHERE 条件を最も選択性の高いものから最も選択性の低いものへと実行します (つまり、戻り値セットのサイズを 80% 削減する結合がある場合は、クエリの一番上に配置します)。オプティマイザーは、理論的には、テーブルの統計に基づいてこれらの条件の結合を並べ替えることができるはずですが、追加の支援を与えると違いが生じる場合があることがわかりました。

  • SQL 実行計画の読み方を学びます。それらは、データベースがリクエストをどのように実行したかを正確に教えてくれます。また、範囲、直接インデックスを使用できたときに、データベースが失敗してインデックスを作成したかどうか (またはパフォーマンスに役立つ可能性のあるインデックスがデータベースにない場合) を知ることができます。ヒット、またはフル テーブル スキャンなど。

  • 非常に長時間実行されるクエリでは、いくつかの予備的な結果を一時テーブルに転用し、そのテーブルに適切にインデックスを付けてから、そのテーブルに対して残りのクエリを実行すると便利な場合があります。これは、結果の一部をより直接的な基準で事前にフィルタリングする戦略を見つけることができる場合に、大きなテーブルのテーブル スキャンを強制する計算基準で結合またはフィルタリングする必要がある場合に特に当てはまります。

于 2013-07-26T06:02:56.030 に答える
1

最良の結果を得るには、最初のテーブルをできるだけ早く削減して、オラクルが破棄する余分な行を大量に作成しないようにします。次に、サブクエリが完了した後ではなく、サブクエリ内にそのフィルターを追加します。私は試してみたい:

SELECT G.ID, T1.QUANTITY, T2.QUANTITY
  FROM GOODS G
  JOIN DUAL ON G.ID IN (1, 2, 3, 4)
  LEFT JOIN (SELECT SUM(QUANTITY) AS QUANTITY, GOOD_ID
          FROM MY_TABLE_1 T
         GROUP BY GOOD_ID
        ) T1 ON T1.GOOD_ID = G.ID
  LEFT JOIN (SELECT SUM(QUANTITY) AS QUANTITY, GOOD_ID
          FROM MY_TABLE_2 T
         GROUP BY GOOD_ID
        ) T2 ON T2.GOOD_ID = G.ID
于 2013-07-26T06:02:56.863 に答える
0

オプティマイザーがほとんどのことを処理します。次のことを行う必要があります 主キーで結合してみてください 可能でない場合は、結合に関係する列のインデックスを提供します 可能な場合 結合する前に、where句を使用して結果をフィルタリングし、ソーステーブルの行を減らします

于 2013-07-26T06:09:00.363 に答える