我有一个表“ 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传递给例程
我认为问题是因为遍历数百万个时间戳的问题,或者其他一些问题。任何输入将不胜感激。 也许还分批处理?如果可以,怎么办?
答案 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
)
这应该使用完整表达式的索引。