PostgreSQL时间序列范围查询

时间:2017-11-09 11:19:39

标签: postgresql

我在Sinatra有一个使用Postgres和ActiveRecord的应用程序。我已将ActiveRecord迁移转换为下面的原始sql:

CREATE TABLE "locations" (
  "id" bigserial primary key,
  "latitude" character varying,
  "longitude" character varying,
  "speed" integer, "course" integer,
  "agent_uuid" character varying,
  "recorded_at" timestamp,
  "created_at" timestamp NOT NULL,
  "updated_at" timestamp NOT NULL
)

CREATE  INDEX  "index_locations_on_agent_uuid_and_recorded_at" ON "locations"  ("agent_uuid", "recorded_at")
CREATE  INDEX  "index_locations_on_recorded_at" ON "locations"  ("recorded_at")

该表格有4m +行的用户位置,可以通过手机进行ping操作。我想为所有用户返回最后5分钟的位置。该查询需要5秒多的时间才能完成,这太长了,理想情况下我希望这个时间不到0.5秒。

我使用以下查询查询db表:

SELECT * FROM 
    locations as l 
  WHERE 
    l.recorded_at >= (DATE '2017-10-20') 
    AND l.recorded_at < (DATE '2017-10-28') 
  ORDER BY 
    recorded_at DESC;

运行EXPLAIN ANALYZE VERBOSE BUFFERS报告:

Sort  (cost=151034.25..151034.57 rows=126 width=85) (actual time=5609.589..5609.662 rows=253 loops=1)
  Output: id, latitude, longitude, speed, course, agent_uuid, recorded_at, created_at, updated_at
  Sort Key: l.recorded_at DESC
  Sort Method: quicksort  Memory: 60kB
  Buffers: shared hit=25051 read=49475
  ->  Seq Scan on public.locations l  (cost=0.00..151029.85 rows=126 width=85) (actual time=314.955..5609.469 rows=253 loops=1)
        Output: id, latitude, longitude, speed, course, agent_uuid, recorded_at, created_at, updated_at
        Filter: ((l.recorded_at >= '2017-10-28 15:00:00'::timestamp without time zone) AND (l.recorded_at < '2017-10-28 15:05:00'::timestamp without time zone))
        Rows Removed by Filter: 5117974
        Buffers: shared hit=25051 read=49475
Planning time: 0.081 ms
Execution time: 5609.721 ms

然而它仍然很慢。有没有人有任何想法如何加快这一点,我不知所措。非常感谢任何想法。

一旦我将迁移运行到index_locations_on_recorded_at,这大大加快了查询速度。迁移后的报告是:

Index Scan Backward using index_locations_on_recorded_at on public.locations l  (cost=0.43..522.07 rows=169 width=85) (actual time=0.040..0.188 rows=253 loops=1)
  Output: id, latitude, longitude, speed, course, agent_uuid, recorded_at, created_at, updated_at
  Index Cond: ((l.recorded_at >= '2017-10-28 15:00:00'::timestamp without time zone) AND (l.recorded_at < '2017-10-28 15:05:00'::timestamp without time zone))
  Buffers: shared hit=235
Planning time: 0.157 ms
Execution time: 0.885 ms

感谢您的帮助。

0 个答案:

没有答案