PostgreSQL遍历数百万条记录?

时间:2019-04-27 13:07:55

标签: php sql postgresql postgis

我有一个表“ location_signals”,其中包含约2.5亿条记录,在ID字段上有一个索引。该表具有ID,时间戳,纬度和经度(以及其他几列未使用的列)。 每个ID可以包含数千个带有不同时间戳的纬度/经度条目。我有一个传递ID的例程,它会获取该ID的所有记录,然后返回一个最高纬度/经度的圆圈。

当我们有一万条记录时,上面的方法效果很好,但是当我们导入更多数据时,它再也无法处理了。逻辑如下:

  • 使用“按ID从location_signals组中选择ID”选择唯一ID(仅限1500),这里的一个问题是数据时间戳不是理想格式,因此可以这样做:

       SELECT TO_TIMESTAMP(timestamp, 'MM/DD/YY HH24:MI') AS ts, * 
        FROM  location_signals 
        WHERE (
        extract(hour from TO_TIMESTAMP(timestamp, 'MM/DD/YY HH24:MI')) > '18' 
        OR  extract(hour from TO_TIMESTAMP(timestamp, 'MM/DD/YY HH24:MI')) < '06'  
        )
        AND \"DID\" = '$did'
    
        LIMIT 1500
    
  • 将ID传递给例程

我认为问题是因为遍历数百万个时间戳的问题,或者其他一些问题。任何输入将不胜感激。 也许还分批处理?如果可以,怎么办?

1 个答案:

答案 0 :(得分:5)

您应该真正地将timestamp列修复为真实的时间戳。将日期/时间值存储为字符串是一个非常糟糕的主意。将列命名为存储为正确的数据类型,好吧,在我看来,这是不正当行为的。

由于要在时间范围内进行搜索,因此可以在表达式上创建索引:

create index idx_location_signals_id_time on location_signals(did, to_timestamp(timestamp, 'MM/DD/YY HH24:MI')::time));

然后,您可以将where逻辑表示为:

where did = ? and
      (to_timestamp(timestamp, 'MM/DD/YY HH24:MI')::time >= '19:00:00'::time or
       to_timestamp(timestamp, 'MM/DD/YY HH24:MI')::time < '06:00:00'::time
      )

这应该使用完整表达式的索引。