web-dev-qa-db-ja.com

2 BツリーインデックスOR 1 tsrangeのGistインデックス-どちらがより良いパフォーマンスを発揮しますか?

starts_atends_atを使用して予約データを格納しているテーブルがあります。テーブルにクエリを実行して重複する予約を見つけるときはいつでも、次のクエリのいずれかを使用するオプションがあります。

SELECT * FROM reservations
WHERE starts_at < '2014-01-03 00:00:00'
AND   ends_at   >='2014-01-01 00:00:00';

または

SELECT * FROM reservations
WHERE tsrange(starts_at, ends_at) && ('2014-01-01 00:00:00', '2014-01-03 00:00:00')

starts_at列とends_at列に通常のBツリーインデックスがあるため、最初のクエリは常にそれらを使用しています。ただし、tsrangeで機能Gistインデックスを定義しない限り、2番目のクエリは完全なスキャンを実行します。

create index tsrange_idx on reservations using Gist(tsrange(starts_at, ends_at)); 

私の質問は、テーブルが大きくなるにつれて、どのインデックスが速くなるのですか?おそらく、答えはクエリ実行プランを見れば明らかですが、私はEXPLAIN ANALYZE出力の読み取りに精通していません。

8
Saurabh Nanda

Bツリーインデックスのタイムスタンプ

3番目のオプションをお勧めします。テーブルに2つのtimestamp列が定義されている限り(これはNOT NULL)単一の multicolumn index withopposedsort order(他の考慮事項が適用されない場合):

CREATE INDEX reservations_range_idx ON reservations using Gist(starts_at, ends_at DESC);

これらの関連する回答の詳細:

クエリについては、 SQL-標準演算子OVERLAPS を見てください。

SELECT * FROM reservations
WHERE (starts_at, ends_at) OVERLAPS ('2014-01-01 00:00:00', '2014-01-03 00:00:00');

SOに関するこの関連質問の詳細:

2つのBツリーインデックスよりも高速である必要があります。ディスク容量が少なく、維持費が安くなります。書き込み操作の負担が少ない

Gistインデックス付きの範囲タイプ

大きなテーブルでは、 範囲型の要旨インデックス の方がスケールが優れているため、おそらく高速です。ただし、ディスク上のストレージはかなり大きく、インデックスのメンテナンスは少しコストがかかります。

そのルートを使用する場合は、タイムスタンプを範囲( tsrangeまたはtstzrange )として最初から格納する方が効率的です。機能的な側面がないプレーンなGistインデックスは少し高速です。

CREATE TABLE reservation (
  reservation_id serial PRIMARY KEY
 ,span tsrange
 , ...
);

CREATE INDEX reservation_span_Gist_idx on reservations USING Gist (span);

とともに - && "overlap" operator 既に質問に表示されています:

SELECT *
FROM   reservation 
WHERE  span && ('2014-01-01 00:00:00', '2014-01-03 00:00:00');

また、除外制約に興味があるかもしれません。これは、上記のようなGistインデックスを自動的に実装する、設計によって重複を除外します。 マニュアルのコード例 があります。 SOに関するこの関連する回答には、より詳細があります:

13