如何从Postgres中的时间戳自动提取日期或编制索引?

时间:2018-10-12 14:50:08

标签: postgresql

我们有一个带有时间戳字段created_at的Postgres表。定期,我们需要找到created_at的日字段为特定数字的所有记录。

我们可以运行类似的查询

select * from table where extract(day from created_at) = 3;

我怀疑这效率不高,即正在执行全表扫描。如果是这样,我可以以某种方式创建索引来使上述方法有效吗?

如果不可能,我们可以创建一个名为created_at_day的单独列并在其上创建索引。

因此我们可以像这样简单地运行查询

select * from table where created_at_day = 3;

假设created_at可以更新。每当发生这种情况时,created_at_day也应该更新。

Postgres是否提供任何支持来自动使created_at_daycreated_at保持同步?如果可以,怎么办?

当然,这可以在应用程序逻辑中完成。因此,无论何时创建或更新created_at,我们都会更新created_at_day列。但是,只是想知道是否有更简单,自动的方法来完成此操作。

谢谢

1 个答案:

答案 0 :(得分:2)

您可以在extract(day from created_at)上创建索引

要查看区别:

创建表格

knayak=# create table t as select i ,now()::timestamp + interval '1 days' * i as created_at from generate_series(1,10000) as i;
SELECT 10000

在created_at

上创建普通索引
knayak=# create index ind_created_at on t(created_at);
CREATE INDEX

knayak=# explain analyze select * from t where extract(day from created_at) = 3;
                                           QUERY PLAN
-------------------------------------------------------------------------------------------------
 Seq Scan on t  (cost=0.00..205.00 rows=50 width=12) (actual time=1.049..6.020 rows=328 loops=1)
   Filter: (date_part('day'::text, created_at) = '3'::double precision)
   Rows Removed by Filter: 9672
 Planning time: 0.392 ms
 Execution time: 6.070 ms
(5 rows)

通过提取创建索引

knayak=# drop index ind_created_at;
DROP INDEX
knayak=# create index ind_created_at on t( extract(day from created_at) );
CREATE INDEX
knayak=# explain analyze select * from t where extract(day from created_at) = 3;
                                                        QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on t  (cost=4.67..61.66 rows=50 width=12) (actual time=0.110..0.260 rows=328 loops=1)
   Recheck Cond: (date_part('day'::text, created_at) = '3'::double precision)
   Heap Blocks: exact=54
   ->  Bitmap Index Scan on ind_created_at  (cost=0.00..4.66 rows=50 width=0) (actual time=0.093..0.093 rows=328 loops=1)
         Index Cond: (date_part('day'::text, created_at) = '3'::double precision)
 Planning time: 0.316 ms
 Execution time: 0.314 ms
(7 rows)