わかりました-試してみます。これは主に利用可能な情報からの控除です:
Oracleが別の実行プランを選択するのはなぜですか?
異常なDate-Formatを使用した2番目のクエリでは、オプティマイザは結果の日付の値が何であるかを認識していないようです。フィルタ述語が表示されます:
1-filter(TO_DATE( '20140610'、'yyyymmdd')<=TO_DATE( '2014-06-10 23:59:59'、'syyyy-mm-dd hh24:mi:ss'))コード>
つまり、オプティマイザーは最初の日付が2番目の日付よりも小さいことさえ確信していません!つまり、オプティマイザーは返される行の数を認識せず、特定の統計を考慮せずに一般的なプランを使用するだけです。範囲の日付を返すユーザー定義関数xyt()がある場合も同じです。オプティマイザーには、結果の日付値を知る方法がありません。これは、一般的な万能プランを取得することを意味します。これは、指定された日付範囲に対してかなり適切なはずです。
1番目と3番目のケースでは、オプティマイザーは日付を直接理解しているようで、統計を使用して日付範囲内の行数を推測できます。したがって、2番目のクエリは BETWEEN X AND 3
のようなオプティマイザに対するものでした。 このクエリはBETWEEN1 AND 3
のようなものです そこで彼は、返される行の予測数に合わせてクエリプランを最適化します!
奇妙なことに、クエリオプティマイザには奇妙な日付形式でこのような問題があり、バグ/改善の要求として提出される可能性があります...
しかし重要なポイント:
- 全表スキャンは悪い計画である必要はありません...インデックスを使用するだけでなく、常に高速であるとは限りません!
- クエリプランのコストは、実際の実行時間やパフォーマンスに直接関係するものではありません。同じクエリのさまざまなプランを比較するための内部測定です(したがって、クエリ1のようにさまざまなクエリのコストを比較することはできません。 、2および3)
基本的に、テーブルから多数の行を返す場合、特に特定のパーティションで操作している場合、インデックスアクセスなしの全表スキャンは多くの場合はるかに高速になります。 -テーブルスキャンは、一致する日付範囲のパーティションにのみアクセスします-したがって、問題の日付に対してのみアクセスし、このパーティションからすべての行を返します。これは、各単一行のインデックスをクエリしてから、インデックスアクセスによって行を抽出するよりもはるかに高速です...クエリのプロファイルを作成してみてください。パーティションの全表スキャンは、IOがはるかに少ない3倍の速度である必要があります。