我们有一个带有时间戳字段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_day
与created_at
保持同步?如果可以,怎么办?
当然,这可以在应用程序逻辑中完成。因此,无论何时创建或更新created_at
,我们都会更新created_at_day
列。但是,只是想知道是否有更简单,自动的方法来完成此操作。
谢谢
答案 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)