2017-11-02 14 views
0

私はこれのようなものを持っています。コードのこの部分では、車両が少なくとも5分間停止したかどうかを検出します。 それは動作しますが、大量のデータでは遅くなります。 私は多くのテストを行い、私の問題はnot existsブロックにあると確信しています。PostgreSQL - 現在のレコード日付と同じ日付に5分を加えたレコードで条件を作成する方法は?

マイテーブル:

CREATE TABLE public.messages 
(
    id bigint PRIMARY KEY DEFAULT nextval('messages_id_seq'::regclass), 
    messagedate timestamp with time zone NOT NULL, 
    vehicleid integer NOT NULL, 
    driverid integer NOT NULL, 
    speedeffective double precision NOT NULL, 
    -- ... few nonsense properties 
) 
WITH (
    OIDS=FALSE 
); 
ALTER TABLE public.messages OWNER TO postgres; 

CREATE INDEX idx_messages_1 ON public.messages 
USING btree (vehicleid, messagedate); 

そして、私のクエリ:

SELECT 
    * 
FROM 
    messages m 
WHERE 
    m.speedeffective > 0 
    and m.next_speedeffective = 0 
    and not exists(-- my problem 
     select id 
     from messages 
     where 
      vehicleid = m.vehicleid 
      and speedeffective > 5 -- I forgot this condition 
      and messagedate > m.messagedate 
      and messagedate <= m.messagedate + interval '5 minutes' 
    ) 

私は、よりパフォーマンスの高い方法で、条件を構築する方法を見つけ出すことはできません。

編集DAY2:

私はのテーブルで使用するには、このような前の表を追加しました:

WITH messagesx as (
    SELECT 
    vehicleid, 
    messagedate 
    FROM 
    messages 
    WHERE 
    speedeffective > 5 
) 

、今は良い作品。私は少し詳しくは分からないと思う。

+0

おそらく私はあなたの質問に答えることはできませんが、定義されたインデックスと一緒にテーブルのDDLを投稿する必要があります – fero

+0

ありがとう@fero。何か追加するには? – Gohchi

答えて

0

通常、 'NOT EXISTS'を選択すると、外部行ごとにテーブルをフルスキャンする必要があるため、クエリが遅くなります。 (私はテーブルを知らなくても、ここでの問合せをリライトしようとしているので、私はここでミスをしたかもしれません)参加中の同じ機能を組み込むために試してみてください:NOTが存在することを

SELECT 
    * 
FROM 
    messages m1 
LEFT JOIN 
    messages m2 
ON m1.vehicleid = m2.vehicleid AND m1.messagedate < m2.messagedate AND m1.messagedate <= m2.messagedate+interval '5 minutes' 
WHERE 
    speedeffective > 0 
    and next_speedeffective = 0 
    and m2.vehicleid IS NULL 

をメモは、次のように書き換えられ結合条件のヒットしません。この回答に基づいて

+0

明日はそれを確認し、うまくいかない場合はデータを追加します。前もって感謝します。 – Gohchi

+0

私は試しましたが、まだまだ時間がかかります。 @CountZukula – Gohchi

0

https://stackoverflow.com/a/36445233/5000827NOT INを読み、NOT EXISTSLEFT JOIN(参加 NULLである)

PostgreSQLのは、NOT EXISTSLEFT JOIN抗参加であり、同じ方法で動作します。 (これは、@CountZukulaの回答が鉱山とほぼ同じ理由です)

問題は操作の種類がNestまたはHashであることにあります。だから、

、これに基づいて:https://www.postgresql.org/docs/9.6/static/routine-vacuuming.html

PostgreSQLのVACUUMコマンドは、いくつかの理由のために、定期的に各テーブルを処理しています更新が占有するディスク領域を回復または再利用するに

  1. か削除された行

  2. PostgreSQLクエリプランナーが使用するデータ統計を更新します。

  3. 可視性マップを更新すると、インデックスのみのスキャンが高速化されます。

  4. トランザクションIDラップアラウンドまたはマルチアクトIDラップアラウンドのために非常に古いデータが失われないようにする。

私はVACUUM ANALYZEにメッセージテーブルを作って、同じクエリが道に高速に動作します。

したがって、VACUUMを使用すると、PostgreSQLがより良く決定できます。

関連する問題