web-dev-qa-db-ja.com

日付範囲クエリに対するOracleのパフォーマンス

特定の組織が特定の期間に渡した注文の数を数えようとしています。しかし、以下のクエリ(2日間の時間範囲)は、1日に2つの個別のクエリを実行するよりもはるかに遅いことがわかりました。

 SELECT COUNT(*)  FROM ORDER_HISTORY
 WHERE organization = 'BA' AND  TIMESTAMP > = TO_DATE('2016-01-05', 'YYYY-MM-DD') 
 AND TIMESTAMP<= TO_DATE('2016-01-05', 'YYYY-MM-DD')+2;

timestampsにインデックスがあり、列organizationに別のインデックスがあります

enter image description here

これが私のテーブルのスキーマです。列timestampはタイプDATEです。

enter image description here

2日間のクエリの実行プランでは、organizationのインデックスを使用します。

enter image description here

1日以上のクエリの実行プランでは、timestampのインデックスを使用します。

enter image description here

いくつかの統計を取得するには:

   SELECT COUNT(*)  FROM ORDER_HISTORY
   WHERE ORGANIZATION = 'BA' ;

2359847を与えます。

   SELECT COUNT(*)  FROM ORDER_HISTORY
   WHERE TIMESTAMP > = TO_DATE('2016-01-05', 'YYYY-MM-DD')
   AND TIMESTAMP<= TO_DATE('2016-01-05', 'YYYY-MM-DD')+1;

9260を返します。2日間の同じクエリは16510を返します。

Oracle DBエンジンの奇妙な動作が発生するのはなぜですか?

2
Gab是好人

その理由は、コストベースのオプティマイザが以前の選択からメモリ内にプランを持っているためです。この場合、特定の組織のレコード数、つまり「LOL」ははるかに少なく、14000程度でした。プランがメモリ内にある場合、CBOパラメータ値はもう関係ありません。使用する:

WHERE organization || '' = 'BA'
1
Gerard H. Pille

オプティマイザ統計が古くなっているか、データに偏りがある(つまり、ORGANIZATION列に人気があり、人気がない)ようです。オプティマイザーは、フィルターORGANIZATION = 'BA'が14898行を返すと推定しますが、これは実際の結果とはかなり異なります。 dbms_stats.gather_table_statsで問題が解決するはずです。 **スクリーンショットによると、「LOL」はEXPLAINで使用される組織の価値のようです。実際の実行計画を投稿することをお勧めします。

2つの列(ORGANIZATION、タイムスタンプ)で拡張統計を作成することもできます。

また、explainの結果ではなく、常に実際の実行計画(dbms_xplan.display_cursor)を確認してください。

更新

問題の調査に役立つもう1つのこと。また、v$sql/v$sqlareaでクエリを検索し、そのコストを確認することをお勧めします。また、v$sqlにはis_bind_aware列とis_bind_sensitive列があり、オプティマイザが異なるプランを考慮して使用するかどうかは、バインド変数の異なる値に依存するかどうかを示します。複数のプランが生成された理由に関するその他の詳細V$SQL_SHARED_CURSORシステムビューは、既存の子カーソルが新しい子カーソルと共有されなかった理由を示します。

1
a1ex07