DYNAMIC_DATE
テキスト値を日付/時刻に変換するスカラー関数()を作成しました。たとえば、DYANMIC_DATE('T-1')
(T-1=今日マイナス1='昨日')は。を返します08-AUG-2012 00:00:00
。日付文字列も受け入れます:DYNAMIC_DATE('10/10/1974')
。
この関数は、CASE
ステートメントを使用して唯一のパラメーターを解析し、に関連する日付を計算しますsysdate
。
スキーマ内のテーブルは使用しませんが、TABLE
型を使用して日付形式の文字列を格納します。
TYPE VARCHAR_TABLE IS TABLE OF VARCHAR2(10);
formats VARCHAR_TABLE := VARCHAR_TABLE ('mm/dd/rrrr','mm-dd-rrrr','rrrr/mm/dd','rrrr-mm-dd');
句で関数を使用するSELECT
と、クエリは1秒未満で返されます。
SELECT DYNAMIC_DATE('MB-1') START_DATE, DYNAMIC_DATE('ME-1') END_DATE
FROM DUAL
日付ディメンションテーブル(合計レコード91311)に対して使用すると、クエリは1秒未満で完了します。
SELECT count(1)
from date_dimension
where calendar_dt between DYNAMIC_DATE('MB-1') and DYNAMIC_DATE('ME-1')
ただし、より大きなテーブル(26,301,317レコード)に対して使用すると、関数に問題が発生するものもあります。
/*
cost: 148,840
records: 151,885
time: ~20 minutes
*/
SELECT count(1)
FROM ORDERS ord
WHERE trunc(ord.ordering_date) between DYNAMIC_DATE('mb-1') and DYNAMIC_DATE('me-1')
ただし、「ハードコードされた」日付を使用した同じクエリは、かなり迅速に返されます。
/*
cost: 144,257
records: 151,885
time: 62 seconds
*/
SELECT count(1)
FROM ORDERS ord
WHERE trunc(ord.ordering_date) between to_date('01-JUL-2012','dd-mon-yyyy') AND to_date('31-JUL-2012','dd-mon-yyyy')
ORDERING_DATE
ベンダーのバニラインストールには、フィールドのインデックスが含まれていません。
両方のクエリのExplainプランは類似しています。
機能付き:
ハードコードされた日付:
- 関数は句
DYNAMIC_DATE
で繰り返し呼び出されていますか?WHERE
- 他に何が格差を説明するのでしょうか?
** 編集 **
NONUNIQUE
ORDERSテーブルにインデックスが追加されました。どちらのクエリも1秒未満で実行されます。どちらのプランも同じ(アプローチ)ですが、機能のある方が低コストです。
DETERMINISTIC
関数からキーワードを削除しました。クエリは1秒未満で実行されました。
- 問題は本当に関数にあるのでしょうか、それともテーブルに関連しているのでしょうか。
- 3年後、このテーブルがさらに大きくなり、キーワードを含めないと、
DETERMINISTIC
クエリのパフォーマンスが低下しますか? DETERMINISTIC
キーワードは関数の結果に影響を与えますか?明日実行DYNAMIC_DATE('T-1')
した場合、今日(2012年8月9日)実行した場合と同じ結果が得られますか?もしそうなら、このアプローチは機能しません。