sql-从postgres中选择时间戳在一定范围内的记录

我在表预订中有timestamp类型的到达列(我正在使用postgres)。例如,我将如何选择今年内的所有日期?

我知道我可以做这样的事情:

select * FROM reservations WHERE extract(year from arrival) = 2012;

但是我已经进行了分析,看起来它需要进行序列扫描。有更好的选择吗?

附言 1毫米 两种方法似乎都需要序列。 扫描。 但是Wildplasser的那款产品能更快地产生结果-为什么?

cmm=# EXPLAIN ANALYZE select * FROM reservations WHERE extract(year from arrival) = 2010;
                                                  QUERY PLAN                                                   
---------------------------------------------------------------------------------------------------------------
 Seq Scan on vrreservations  (cost=0.00..165.78 rows=14 width=4960) (actual time=0.213..4.509 rows=49 loops=1)
   Filter: (date_part('year'::text, arrival) = 2010::double precision)
 Total runtime: 5.615 ms
(3 rows)

cmm=# EXPLAIN ANALYZE SELECT * from reservations WHERE arrival > '2010-01-01 00:00:00' AND arrival < '2011-01-01 00:00:00';
                                                                  QUERY PLAN                                                                   
-----------------------------------------------------------------------------------------------------------------------------------------------
 Seq Scan on reservations  (cost=0.00..165.78 rows=51 width=4960) (actual time=0.126..2.491 rows=49 loops=1)
   Filter: ((arrival > '2010-01-01 00:00:00'::timestamp without time zone) AND (arrival < '2011-01-01 00:00:00'::timestamp without time zone))
 Total runtime: 3.144 ms
(3 rows)

**附言 2-在到达列上创建索引后,第二种方法甚至更快-因为看起来查询使用索引。 Mkey-我想我会为此而感到震惊。 **

                                                                       QUERY PLAN                                                                        
---------------------------------------------------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on reservations  (cost=4.77..101.27 rows=51 width=4960) (actual time=0.359..0.791 rows=49 loops=1)
   Recheck Cond: ((arrival > '2010-01-01 00:00:00'::timestamp without time zone) AND (arrival < '2011-01-01 00:00:00'::timestamp without time zone))
   ->  Bitmap Index Scan on arrival_idx  (cost=0.00..4.76 rows=51 width=0) (actual time=0.177..0.177 rows=49 loops=1)
         Index Cond: ((arrival > '2010-01-01 00:00:00'::timestamp without time zone) AND (arrival < '2011-01-01 00:00:00'::timestamp without time zone))
 Total runtime: 1.265 ms
zzz asked 2020-06-27T15:14:55Z
2个解决方案
66 votes
SELECT * 
FROM reservations 
WHERE arrival >= '2012-01-01'
AND arrival < '2013-01-01'
   ;

顺便说一句,如果值的分布表明索引扫描将不值得(例如,如果所有值都在2012年),那么优化器仍可以选择全表扫描。 YMMV。 说明是你的朋友。

wildplasser answered 2020-06-27T15:15:13Z
6 votes

使PostgreSQL对原始查询使用索引的另一种方法是在所使用的表达式上创建索引:

create index arrival_year on reservations ( extract(year from arrival) );

这将打开PostgreSQL,并可能将索引用于

select * 
FROM reservations 
WHERE extract(year from arrival) = 2012;

请注意,索引中的表达式必须与where子句中使用的表达式完全相同才能使此工作有效。

a_horse_with_no_name answered 2020-06-27T15:15:42Z
translate from https://stackoverflow.com:/questions/12438990/select-records-from-postgres-where-timestamp-is-in-certain-range