1

ブログを作成していますが、問題があります。粘着性のある投稿がいくつかあるはずです。私が望むのは、最初にスティッキーポストを取得し、次に残りを取得することだけです.

機能するクエリの1つは

select * from 

(
(select *,true as st from blog where "stickyUntil" > current_timestamp) 
UNION  all
(SELECT *,false as st from blog where "stickyUntil" < current_timestamp  or "stickyUntil" is null  ) 
) q 


order by st desc, "stickyUntil" DESC ,publish DESC OFFEST x LIMIT z

workz のもう 1 つの簡単なクエリは次のとおりです。

select * from blog order by case when "stickyUntil" > current_timestamp then "stickyUntil" end desc nulls last, publish desc;

しかし、これは200.000行をメモリ内でソートすることを強制し、それほど速くはありません..

それを最適化する方法はありますか??

2 つの別々のクエリを使用する方がよいでしょうか? ありがとう

4

3 に答える 3

3

テーブルの 2 回のパスを避けるために、CASEステートメントを使用します。

select *, 
   CASE 
   WHEN "stickyUntil" > current_timestamp THEN true
   ELSE false
   END as st
FROM blog
ORDER BY st DESC ,publish DESC OFFEST x LIMIT z

Postgres は、ここで役立つ計算フィールドでのINDEXの作成をサポートしていますが、制限があります。

インデックス定義で使用されるすべての関数と演算子は「不変」である必要があります。つまり、それらの結果は引数のみに依存し、外部の影響 (別のテーブルの内容や現在の時間など) には決して依存しない必要があります。

そのため、 st計算にインデックスを付けることはできません。stの計算があまり正確である必要がない場合は、stフィールドをテーブルに追加するという別のオプションがあります。

ALTER TABLE blog
ADD COLUMN st boolean default true

通常の列としてのINDEX st :

CREATE INDEX sti ON blog(st)

そして定期的に実行します:

UPDATE blog
SET st = false
WHERE st = true
AND "stickyUntil" < current_timestamp

しかし、ポーリング プロセスで更新を行うことは、単純なクエリよりもはるかに魅力的ではありません。これは、クエリが非常に遅いか、ブログテーブルの読み取りが多い場合にのみ意味があります。

于 2012-05-30T00:57:05.250 に答える
1

スティッキー投稿用と残り用の 2 つのクエリを実行するのが最善だと思います。

SQL は、明示的な order by がなければ、結果の順序付けを保証しません。UNION ALL を使用した結果は正しいように見えるかもしれませんが、保証はできません。これは、どのスレッドが最初にデータの読み取りを終了し、結果を返し始めるかわからないマルチスレッド環境でより顕著になります。

最も効率的な回避策は、2 つの異なるクエリとして実行することです。

于 2012-05-30T02:34:14.190 に答える
0
select * 
from blog
order by 
    coalesce("stickyUntil", '1901-01-01'::date) < current_timestamp, 
    publish DESC 
OFFSET x LIMIT z
于 2012-05-30T11:28:48.443 に答える