我有一张有数十亿行的表。“记录”字段有每日分区,是“无时区的时间戳”。我想知道表中当前有哪些日期。我知道我可以做类似的事情:
SELECT recorded::date
FROM table
GROUP BY 1;
理想情况下应该可以工作,但是对此的解释相当高,并且表明需要很长时间才能工作...如果这是我能做的最好的事情,我可以接受(并且我们可以密切关注数据)进去),但我想知道是否有更有效的方法来做到这一点,因为我每天都有分区?
我有一张有数十亿行的表。“记录”字段有每日分区,是“无时区的时间戳”。我想知道表中当前有哪些日期。我知道我可以做类似的事情:
SELECT recorded::date
FROM table
GROUP BY 1;
理想情况下应该可以工作,但是对此的解释相当高,并且表明需要很长时间才能工作...如果这是我能做的最好的事情,我可以接受(并且我们可以密切关注数据)进去),但我想知道是否有更有效的方法来做到这一点,因为我每天都有分区?
您可以像这样创建索引:
create index your_index_name
on table (date_trunc('day', recorded))
在我的测试中,PostgreSQL 9.something 在添加索引之前使用顺序扫描,在简单地为“记录”列建立索引之后进行顺序扫描,并在使用 date_trunc() 对其进行索引之后进行索引扫描。选择一天的行在没有索引的情况下需要 66 毫秒,在普通索引情况下需要 68 毫秒,在使用 date_trunc() 的情况下需要 13 毫秒。
对于数十亿行,预计创建该索引需要几分钟时间。(咳嗽)
这里有一个非常相似的线程:
如果您知道最小/最大日期,则最好查询日期列表而不是对整个表进行 seq 扫描。假设你有一个记录的索引,看起来像这样的东西应该更快:
with days as (
select date_trunc('day', min(recorded))::date + k * interval '1 day' as day
from records,
generate_series(0,
(select date_trunc('day', max(recorded))::date
- date_trunc('day', min(recorded)::date
from records
)) as k
)
select day
from days
where exists (
select 1
from records
where day <= recorded and recorded < day + interval '1 day'
);
上面的查询可能需要做一些调整,但总体思路是:在索引字段上执行数千次子查询/索引扫描比对数十亿行进行 seq 扫描更快,并且聚合它们以识别不同的日期。