1

製品予測データを 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 つの独立したクエリの結合として設定するだけでよいことはわかっていますが、最適化エンジンに関して正確に何が起こっているのか興味があります。実行計画、それが役立つ場合。

ありがとう!

4

1 に答える 1

0

テーブルがすべて分析されていることを確認してください。再びそれを行う。オプティマイザーは、これらの値を使用して実行計画を計算します。Oracle が実際に間違った計画を選択した場合の回避策は、ヒント /*+ ... */ を使用してオプティマイザにインデックスの使用、結合順序などを指定するよう強制することです。

于 2013-07-29T20:46:43.733 に答える