TIMESTAMP(6)
列にインデックスがある場合、この列をTIMESTAMP(6)
として使用して、インデックスの利点を得る必要がありますか?この列を2番目の精度の数値(YYYYMMDDHHmmss
)に変換しても、インデックスのパフォーマンスを実現できますか?
例えば:
SELECT * FROM MYTABLE
WHERE TO_NUMBER(TO_CHAR(MYCOLUMN, 'YYYYMMDDHH24MISS'), '99999999999999') > 20110622105738
AND TO_NUMBER(TO_CHAR(MYCOLUMN, 'YYYYMMDDHH24MISS'), '99999999999999') <= 20150622105738
ORDER BY MYCOLUMN
これはOracle 11用です
mycolumn
に単純なbツリーインデックスがある場合、はい、そのインデックスを使用して行をフィルター処理できるようにするために、その列で関数を呼び出さないようにする必要があります。この場合、数値リテラルをタイムスタンプに変換する方が、逆を行うよりもはるかに理にかなっているようです
SELECT * FROM MYTABLE
WHERE my_column > to_timestamp( to_char(20110622105738), 'YYYYMMDDHH24MISS' )
AND my_column <= to_timestamp( to_char(20150622105738), 'YYYYMMDDHH24MISS' )
ORDER BY MYCOLUMN
これで、関数ベースのインデックスを作成することもできます
create index idx_my_fbi
on mytable( TO_NUMBER(TO_CHAR(MYCOLUMN, 'YYYYMMDDHH24MISS'), '99999999999999') );
元のクエリで使用できるもの。
もちろん、どちらの場合でも、Oracleが実際にインデックスを使用するかどうかは、述語がどの程度選択的であると期待するかに依存します。 4年分のデータを返すので、使用する資格があるとしても、インデックスが有益であるとは考えられません。テーブルに数百年分のデータが含まれていない限り、テーブルスキャン(またはテーブルがパーティション化されている場合は1つ以上のパーティションのフルスキャン)は、より適切なクエリプランのように見えます。
あなたが探している解決策は、元のデータ自体ではなく、式にインデックスを作成することに関係していると思います。外部参照については、 Wikipedia または Oracleのドキュメント を参照してください。ここのリンクには、「関数ベースのインデックス」セクションの詳細と後続のリンクが含まれています。このようなインデックスの使用には関連するコストとメリットがあるため、それがユースケースに一致するかどうかを確認するのはあなた次第です。
一般的な例を考えてみると、_order_table
_という名前のdate
列とvarchar(250)
列名_order_date
_を含むテーブル_order_info
_があるとしますが、注文の月に基づいて頻繁にクエリを実行したい。この場合、実行中
_SELECT order_info, EXTRACT(month FROM order_date) "month"
FROM order_table
WHERE month = ....
_
本質的に、すべての「月」値を抽出して、それらがWHERE
述部を満たすかどうかを判別する必要があります。 _order_date
_列にインデックスを作成した場合でも、インデックスのすべてのエントリに対して月を計算する必要があるため、インデックスは役に立ちません。 (Aside:したがって、オプティマイザがインデックスをスキャンして有効な月を抽出し、テーブルから読み取ることを選択するスマートクエリプランを想定できます関連するRowIDです。この場合、インデックスがあると役立ちますが、式にインデックスを付けるほどではありません...)
このクエリパターンが非常に一般的で、そのようなインデックスを維持するためのコストの増加を正当化できる場合は、式の出力にインデックスを付けるだけでメリットがあります。
_CREATE INDEX idx_month_order_date ON order_table (EXTRACT(month FROM order_date));
_
次に、上記のようなクエリを実行すると、プランナはインデックスを利用してクエリをはるかに高速化できるはずです。
お役に立てれば!