簡単なクエリ
最初の例は、date
最初の質問に従って列を処理します。
Rubyの構文についてはよくわかりませんが、適切なSQLステートメントは次のようになります。
SELECT *
FROM tbl
ORDER BY @(date_col - '2012-12-29'::date)
@
「絶対値」演算子です。
date
またはtime
識別子として使用しないでください。PostgreSQLでは(いくつかの制限付きで)許可されていますが、これらはSQL標準で予約語であり、混乱を招くエラーメッセージや予期しないエラーにつながる可能性があります。
最高のパフォーマンス
残りtimestamp
は、コメントの更新に従って列で機能します。
小さなテーブルやアドホッククエリの場合、上記のソリューションで十分です。中規模または大規模のテーブルの場合、パフォーマンスが重要な場合は、より洗練されたアプローチをお勧めします。
Condicio sine qua nonは、または列のインデックスです。このような:date
timestamp
CREATE INDEX tbl_my_timestamp_idx ON tbl(my_timestamp);
インデックスを配置すると、次のクエリが実行され、より大きなテーブルの単純なクエリのパフォーマンスが低下します。
SELECT *
FROM (
(
SELECT *
FROM tbl
WHERE my_timestamp >= '2012-12-30 11:32'::timestamp
ORDER BY my_timestamp
LIMIT 3
)
UNION ALL
(
SELECT *
FROM tbl
WHERE my_timestamp < '2012-12-30 11:32'::timestamp
ORDER BY my_timestamp DESC
LIMIT 3
)
) x
ORDER BY @extract('epoch' FROM (my_timestamp - '2012-12-28 11:32'::timestamp))
LIMIT 3;
どうして?
最初のクエリは、条件として式を使用します。Postgresはすべての行の値を計算し、結果で並べ替えて最初の数行を選択する必要があります。小さなテーブルでは問題ありませんが、大きなテーブルでは非常に高価です。O(n) ; n
テーブルの行数です。プレーンインデックスは使用できません。さらに、すべての行の中から勝者を並べ替えて選択するための重要なコストがあります。
式にインデックスを作成することもできますが、これは最速ですが、比較するために一定のタイムスタンプに対してのみ機能します。現実的なユースケースとは言えません。
2番目のクエリは、インデックス内のタイムスタンプに従って位置を検索し、次の2行のタプルポインタを順番に読み取り、テーブルから直接(または、9.2のインデックスのみのスキャンでインデックスから直接)フェッチします。ピアがどのように比較されるかわからないので、2回、1回アップ、1回ダウン。ただし、これは2 x O(log(n))(通常のbツリールックアップコスト)です。計算は、事前に選択されたいくつかの行に対してのみ実行されます。小さなサンプルから勝者を選ぶことは、取るに足らない一定のコストを伴います。
でテストするだけEXPLAIN ANALYZE
です。実際のテーブルでの簡単なテストで、5万行のテーブルで係数1000を取得しました。そして、それはより大きなテーブルのためにスケールアップし続けます。