【问题标题】:select records from postgres where timestamp is in certain range从时间戳在一定范围内的 postgres 中选择记录
【发布时间】:2012-09-15 16:12:08
【问题描述】:

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

我知道我可以这样做:

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

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

附注1 嗯。两种方式似乎都需要seq。扫描。但是,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

【问题讨论】:

  • 5.615 毫秒,是不是太慢了? 3.144 毫秒更好,但没有人会看到 2 毫秒的差异。 EXTRACT() 是一个函数,看起来比两个运算符比较慢。
  • @Frank Heikens Right - 这是因为到目前为止表中只有大约 5000 行 - 还会更多。
  • 顺便说一句:您的查询计划显示的估计行大小为 4960,这是巨大
  • @wildplasser 这是什么意思?行大小为 4960?
  • 这意味着您有非常大的行(许多列和/或大列)。这可能表明数据模型欠佳。

标签: sql postgresql


【解决方案1】:
SELECT * 
FROM reservations 
WHERE arrival >= '2012-01-01'
AND arrival < '2013-01-01'
   ;

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

【讨论】:

  • 只考虑日期,不考虑时间。
  • 对于时间戳,它的工作原理相同。注意:OQ 中的时间字段都是 00:00:00
【解决方案2】:

另一个让 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 : WRT exactly 相同的表达式:我使用CREATE INDEX reservations_yar ON reservations (date_part('year' , arrival)); 进行检查,即使查询使用@ 987654325@ 语法。所以:表达式在比较/搜索之前被规范化。
【解决方案3】:

在 postgress 中搜索时间戳列直到秒

select * from "TableName" e
    where timestamp >= '2020-08-08T13:00:00' and timestamp < '2020-08-08T17:00:00';

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-09
    • 1970-01-01
    • 1970-01-01
    • 2012-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多