あなたの問題は、多くの LEFT JOIN を実行していて、それらすべての JOIN を適用した後に最終的な結果セットが大きくなりすぎることだと思います。また、可能な限り高速な方法で MIN または MAX を計算するために、この方法でインデックスを使用することはできません。インデックスをうまく使用すると、MIN または MAX を非常に迅速に計算できるはずです。
クエリは次のように記述します。
SELECT t1.id,
(SELECT MIN(t5.date) FROM t5 JOIN t4 ON t5.p_id = t4.p_id WHERE t4.id = t1.id) AS first_pri_date,
(SELECT MIN(date) FROM t3 WHERE t3.id = t1.id) AS first_pub_date,
(SELECT MAX(date) FROM t3 WHERE t3.id = t1.id) AS last_publ_date,
(SELECT MIN(date) FROM t2 WHERE t2.id = t1.id) AS first_exp_date
FROM t1
ORDER BY t1.id;
パフォーマンスを向上させるには、(id, date)またはにインデックスを作成します(p_id, date)。したがって、インデックスは次のようになります。
CREATE INDEX ix2 ON T2 (id,date);
CREATE INDEX ix3 ON T3 (id,date);
CREATE INDEX ix5 ON T5 (p_id,date);
CREATE INDEX ix4 ON T4 (id);
t4しかし、との間の結合にはまだ問題が残っていt5ます。と が 1 対 1 の関係にある場合t1、t42 行目に次のように書くとさらによいでしょう。
(SELECT MIN(t5.date) FROM t5 WHERE t5.p_id = (SELECT p_id FROM t4 WHERE t4.id=t1.id)) AS first_pri_date,
1:N で、CROSS APPLY と OUTER APPLY が Oracle バージョンで動作する場合は、2 行目を次のように書き換えることができます。
(SELECT MIN(t5min.PartialMinimum)
FROM t4
CROSS APPLY
(
SELECT PartialMinimum = MIN(t5.date)
FROM t5
WHERE t5.p_id = t4.p_id
) AS t5min
WHERE t4.id = t1.id)
AS first_pri_date
これはすべて、MIN または MAX の計算中にインデックスを最大限に活用することを目的としています。したがって、SELECT 全体は次のように書き直すことができます。
SELECT t1.id,
(SELECT MIN(t5min.PartialMinimum)
FROM t4
CROSS APPLY
(
SELECT TOP 1 PartialMinimum = date
FROM t5
WHERE t5.p_id = t4.p_id
ORDER BY 1 ASC
) AS t5min
WHERE t4.id = t1.id) AS first_pri_date,
(SELECT TOP 1 date FROM t2 WHERE t2.id = t1.id ORDER BY 1 ASC) AS first_exp_date,
(SELECT TOP 1 date FROM t3 WHERE t3.id = t1.id ORDER BY 1 ASC) AS first_pub_date,
(SELECT TOP 1 date FROM t3 WHERE t3.id = t1.id ORDER BY 1 DESC) AS last_publ_date
FROM t1
ORDER BY 1;
これは、履歴データ テーブルから MIN または MAX を取得する最も最適な方法であると私が信じているとおりです。
ポイントは、MIN を多くのインデックスなしの値で使用すると、サーバーがすべてのデータをメモリにロードし、インデックスなしのデータから MIN または MAX を計算することです。これには、I/O 操作の要求が高いため、時間がかかります。 . MIN または MAX を使用するときにインデックスを不適切に使用すると、すべての履歴テーブル データがメモリにキャッシュされ、MIN または MAX の計算以外には必要ないという状況につながる可能性があります。
クエリの CROSS APPLY 部分がなければ、サーバーは t5 からすべての個々の日付をメモリにロードし、ロードされた結果セット全体から MAX を計算する必要があります。
適切にインデックス付けされたテーブルの MIN 関数は、非常に高速な TOP 1 ORDER BY のように動作することに注意してください。このようにして、すぐに結果を得ることができます。
CROSS APPLY は Oracle 12C で使用できます。それ以外の場合は、パイプライン関数を使用できます。
このSQL Fiddle、特に実行計画の違いを確認してください。