製品予測データを Oracle スター スキーマ データベースの過去の出荷データに関連付けるためにこのクエリを作成しましたが、オプティマイザーが期待どおりに動作しなかったため、何が起こっているのか興味があります。
基本的に、予測テーブルと販売ファクト テーブルの両方で一貫性のあるディメンション テーブルが多数ありますが、ファクト テーブルは異なるレベルで集計されるため、それらを 2 つのサブクエリとして設定し、それらをロールアップして結合できるようにします。この場合、すべての予測データが必要ですが、一致する売上データのみが必要です。
奇妙なことに、サブクエリのいずれかを単独で使用すると、それぞれが期待どおりに動作するように見え、それぞれが 1 秒もかからずに返されます (同じフィルターを使用して、いずれかのサブクエリを削除するだけでテストしました)。およびエイリアスの変更)。
クエリ構造の例を次に示します。できる限り一般的なものにしています。変更すると、いくつかのタイプミスがある可能性があります。
SELECT
TIME_DIMENSION.GREGORIAN_DATE,
LOCATION_DIMENSION.LOCATION_CODE,
DESTINATION_DIMENSION.REGION,
PRODUCT_DIMENSION.PRODUCT_CODE,
SUM(NVL(FIRST_SUBQUERY.VALUE,0)) VALUE1,
SUM(NVL(SECOND_SUBQUERY.VALUE,0)) VALUE2
FROM
TIME_DIMENSION,
LOCATION_DMENSION SOURCE_DIMENSION,
LOCATION_DIMENSION DESTINATION_DIMENSION,
PRODUCT_DIMENSION,
(SELECT
FORECAST_FACT.TIME_KEY,
FORECAST_FACT.SOURCE_KEY,
FORECAST_FACT.DESTINATION_KEY,
FORECAST_FACT.PRODUCT_KEY,
SUM(FORECAST_FACT.VALUE) AS VALUE,
FROM FORECAST_FACT
WHERE [FORECAST_FACT FILTERS HERE]
GROUP BY
FORECAST_FACT.TIME_KEY,
FORECAST_FACT.SOURCE_KEY,
FORECAST_FACT.DESTINATION_KEY) FIRST_SUBQUERY
LEFT JOIN
(SELECT
--This is just as an example offset
(LAST_YEAR_FACT.TIME_KEY + 52) TIME_KEY,
LAST_YEAR_FACT.SOURCE_KEY,
LAST_YEAR_FACT.DESTINATION_KEY,
FORECAST_FACT.PRODUCT_KEY,
SUM(LAST_YEAR_FACT.VALUE) AS VALUE,
FROM LAST_YEAR_FACT
WHERE [LAST_YEAR_FACT FILTERS HERE]
GROUP BY
LAST_YEAR_FACT.TIME_KEY,
LAST_YEAR_FACT.SOURCE_KEY,
LAST_YEAR_FACT.DESTINATION_KEY) SECOND_SUBQUERY
ON
FORECAST_FACT.TIME_KEY = LAST_YEAR_FACT.TIME_KEY
AND FORECAST_FACT.SOURCE_KEY = LAST_YEAR_FACT.SOURCE_KEY
AND FORECAST_FACT.DESTINATION_KEY = LAST_YEAR_FACT.DESTINATION_KEY
--I also tried to tie the last_year subquery to the dimension tables here
WHERE
FORECAST_FACT.TIME_KEY = TIME_DIMENSION.TIME_KEY
AND FORECAST_FACT.SOURCE_KEY = SOURCE_DIMENSION.LOCATION_KEY
AND FORECAST_FACT.DESTINATION_KEY = DESTINATION_DIMENSION.LOCATION_KEY
AND FORECAST_FACT.PRODUCT_KEY = PRODUCT_DIMENSION.PRODUCT_KEY
--I also tried, separately, to tie the last_year subquery to the dimension tables here
AND TIME_DIMENSION.WEEK = 'VALUE'
AND SOURCE_DIMENSION.SOURCE_CODE = 'VALUE'
AND DESTINATION_DIMENSION.REGION IN ('VALUE', 'VALUE')
AND PRODUCT_DIMENSION.CLASS_CODE = 'VALUE'
GROUP BY
TIME_DIMENSION.GREGORIAN_DATE,
SOURCE_DIMENSION.LOCATION_CODE,
DESTINATION_DIMENSION.REGION,
PRODUCT_DIMENSION.PRODUCT_CODE
基本的に、いずれかのサブクエリを個別に実行すると、インデックスが利用され、特定のパーティションの特定の範囲のみが検索されますが、左結合では、常にファクト テーブルの 1 つでフル テーブル スキャンが実行されます。起こっているように見えるのは、Oracle がディメンション テーブル フィルターを最初のサブクエリのみに適用していることです。したがって、左結合を行うには、最初に sales テーブル全体をスキャンする必要があります。暗黙のフィルタリングに頼る...私はそれを試しました。私はこれについて間違って考えていますか?私にとって、オプティマイザーは両方のファクト テーブルのインデックスを使用して、WHERE 句の値でそれぞれをフィルター処理し、結果のサブセットを左結合する必要があります。
サブクエリのそれぞれにフィルタを追加するか、これを 2 つの独立したクエリの結合として設定するだけでよいことはわかっていますが、最適化エンジンに関して正確に何が起こっているのか興味があります。実行計画、それが役立つ場合。
ありがとう!