2

以下を含むクエリがあります (ただし、他の結合、テーブル、および where 条件があります)。

SELECT
    o.contact_id, 
    o.completed_date, 
    o.submitted_date
FROM
    orders o /* 860,000 row table */
WHERE   
    ? <= o.submitted_date
    AND o.submitted_date < ? + 1

Java アプリケーションから呼び出されます。

パラメータにより、2 つの?日付の間に送信された注文を確認できます。

ただし、このクエリの実行は非常に遅くなります。

次のように、テストのために PL/SQL から実行するように変換しました。

SubmittedDateFrom date:=to_date('2011-07-15', 'yyyy-mm-dd');
SubmittedDateTo date:=to_date('2011-07-15', 'yyyy-mm-dd');
CURSOR c_orgs    IS    
SELECT
    o.contact_id, 
    o.completed_date, 
    o.submitted_date
FROM
    orders o
WHERE   
    SubmittedDateFrom <= o.submitted_date
    AND o.submitted_date < SubmittedDateTo + 1;
BEGIN
    FOR c_o IN c_orgs LOOP
        DBMS_OUTPUT.put_line('Submitted date = '||c_o.submitted_date);                               
    END LOOP;
END;

次のいずれかの場合:

  1. SubmittedDateTo値を変換しますto_date('2011-07-16', 'yyyy-mm-dd')(つまり、クエリの外側で算術演算を行います)。
  2. SubmittedDateTo文字列を作成to_date('SubmittedDateTo', 'yyyy-mm-dd')し、 の 2 番目の条件として "+1" を使用しWHEREます。

その後、クエリは劇的に高速化されます (< 1 秒対 44+ 秒)。

さらに詳しい情報:

  • クエリで実行計画を実行すると、エラーが発生しますORA-00932: inconsistent datatypes: expected DATE got NUMBER
  • 列にはインデックスがあり、submitted_date統計などが実行されています
  • を呼び出しにラップしてSubmittedDateTo + 1も、trunc()パフォーマンスには影響しません
  • Oracle のバージョンであるかどうかをテストするために、同様のデータ ボリュームなどを備えた 9i 以外のデータベースはありません。

問題は、Oracle 9i Optimizer がこの種の日付計算に問題があることを明確に示す情報を見つけることができないということです。それがここで起こっていることですか、それとも何か他のことが起こっていますか?

4

2 に答える 2

1

すべての変換が明示的に処理されることを常に確認します (そして、o.submitted_date が DATE データ型であると仮定します):

DECLARE
  CURSOR c_orgs    
  IS
     SELECT o.contact_id,      
            o.completed_date,
            o.submitted_date 
       FROM orders o 
      WHERE o.submitted_date BETWEEN TO_DATE(SubmittedDateFrom, 'yyyy-mm-dd') 
                                 AND TO_DATE(SubmittedDateTo, 'yyyy-mm-dd'); 
BEGIN
   FOR c_o IN c_orgs 
   LOOP
      DBMS_OUTPUT.put_line('Submitted date = '||c_o.submitted_date);
   END LOOP;
END; 

これにより、暗黙的な変換でエラーが発生せず、すべての変換がデータ型で明確になります。

「問題は、Oracle 9i オプティマイザーがこの種の日付演算に問題があることを明確に示す情報を見つけることができないということです。それはここで何が起こっているのでしょうか、それとも何か他のことが起こっているのでしょうか?」

オプティマイザーではないと思います。暗黙の変換の最終製品がパフォーマンスの問題を引き起こしている可能性があります。Oracle データベースからの日付などの NLS 設定がないため、わかりにくいかもしれませんが、明示的な変換を使用するとパフォーマンスが向上する場合は、それらを使用することをお勧めします (また、より良い方法です)。

それが役立つことを願っています、Ollie。

于 2011-08-08T15:06:15.047 に答える
1

Oracleのドキュメント(これはv10ですが、これは9iにも当てはまると思います)によると、「...日付バインド変数の暗黙的な型変換を実行するステートメントのEXPLAIN PLANはサポートされていません。」

Ollie によって提案されたアプローチとは別に、trunc() resp を使用してみましたか。代わりに?

SELECT
    o.contact_id, 
    o.completed_date, 
    o.submitted_date
FROM
    orders o /* 860,000 row table */
WHERE   
    trunc(o.submitted_date) = trunc(?)

それぞれ

SELECT
    o.contact_id, 
    o.completed_date, 
    o.submitted_date
FROM
    orders o /* 860,000 row table */
WHERE   
    o.submitted_date between ? and ? + 1
于 2011-08-08T15:09:24.433 に答える