2017-09-25 18 views
0

以下のSQLを使用して文字列に保持されている日付範囲に基づいて行を選択していますが、効率的な方法です。あなたが見ることができるように、日付と時間は異なるフィールドで保持されています。私の記憶から、あるいはOracleの仕事をするとすぐに、属性の周りに関数を置くと、インデックスは使用できません。日付と時刻を組み合わせたPostgresは効率的です

select * 
from events 
where venue_id = '2' 
and  EXTRACT(EPOCH FROM (start_date + start_time)) 
between EXTRACT(EPOCH FROM ('2017-09-01 00:00')::timestamp) 
and  EXTRACT(EPOCH FROM ('2017-09-30 00:00')::timestamp) 

インデックスを使用できる方法はありますか?

+3

なぜエポックを抽出するのですか?どうして 'start_date + start_time BETWEEN '2017-09-01 00:00' :: timestamp AND '2017-09-30 00:00' :: timestamp'ですか? – Andreas

答えて

1

はじめに:クエリは単一のvenue_idに限定されているため、以下の両方の例では、最初にvenue_idの複合インデックスを作成しています。

あなたはそのクエリを改善するための指標が必要な場合、あなたはexpression indexを作成することができます。

CREATE INDEX events_start_idx 
ON events (venue_id, (EXTRACT(EPOCH FROM (start_date + start_time)))); 

専用の機能インデックスをしたくない場合は、あなたがstart_dateに通常のインデックスを作成することができます索引を使用する余分なロジックを追加します。索引によってアクセス・プランが日付範囲に制限され、最初と最後の日付の間違った時間帯のフリンジ・レコードが除外されます。

以下では、エポックの不要な抽出も取り除いています。

CREATE INDEX events_venue_start 
ON events (venue_id, start_date); 
SELECT * 
FROM events 
WHERE venue_id = '2' 
AND  start_date BETWEEN '2017-09-01'::date AND '2017-09-30'::date 
AND  start_date + start_time BETWEEN '2017-09-01 00:00'::timestamp 
            AND '2017-09-30 00:00'::timestamp 

WHERE句の最初の2つの部分は、完全な利益のためにインデックスを使用します。最後の部分は、インデックスによって検出されたレコードをフィルタで使用します。

+0

'start_date BETWEEN' 2017-09-01 ':: date AND' 2017-09-30 ':: date'は実際に必要ですか? –

+0

@BenEdwardsそうでなければ、インデックスを完全に使用することはできません。 – Andreas

関連する問題