【问题标题】:PostgreSQL: Create an index on timestamp::DATE [duplicate]PostgreSQL:在时间戳::日期上创建索引 [重复]
【发布时间】:2016-01-11 14:53:10
【问题描述】:

我正在创建一个汇总表,用于汇总给定日期的所有事件。

INSERT INTO graph_6(
  day,
  event_type,
  (SELECT COUNT(*) FROM event e 
                  WHERE event_type = e.event_type 
                  AND creation_time::DATE = sq.day)
FROM event_type
CROSS JOIN
    (SELECT generate_series(
                (SELECT '2014-01-01'::DATE),
                (SELECT '2014-01-02'::DATE),
                '1 day') as day) sq;

creation_time 列已编入索引:

CREATE INDEX event_creation_time_date_idx ON event USING BTREE(creation_time);

但是,即使只查询包含少量事件的两天数据(2014 年 1 月 1 日至 2 日),查询也会运行相当长的时间。

查询中的EXPLAIN 非常糟糕——它对event 表运行顺序扫描,根本不使用索引:

->  Seq Scan on event e_1  (cost=0.00..12557.39 rows=531 width=38)
Filter: ... AND ((creation_time)::date = (generate_series(($12)::timestamp with time zone, ($13)::timestamp with time zone, '1 day'::interval))))

我认为这是因为我们比较了一个转换值 - creation_time::DATE,而不是 creation_time。我已经尝试为演员编制索引:

CREATE INDEX event_creation_time_date_idx ON event USING BTREE(creation_time::DATE);

但出现错误:

ERROR: syntax error at or near "::"

有没有办法在转换为 DATE 的时区列上使用 PostgreSQL 索引?

【问题讨论】:

  • 我是否因为太多的 SQL JOIN 而失去了 JOIN?这是一个 JOIN 问题 我在不到一个月前提出的问题 的 JOIN 副本。 JOIN假期和JOIN好JOIN书JOIN JOIN JOIN!

标签: sql postgresql date indexing casting


【解决方案1】:

索引声明中的表达式应该用额外的括号括起来,试试:

CREATE INDEX event_creation_time_date_idx ON event ((creation_time::DATE));

【讨论】:

  • 拯救了我的一天 :)
  • 这仅适用于没有时区的时间戳。否则你会得到这个错误:错误:索引表达式中的函数必须标记为 IMMUTABLE
  • 如果您选择一个时区并在索引和查询中转换为它,您可以绕过时区问题(某种程度):creation_time AT TIME ZONE 'UTC'
  • 如果您使用@thaddeusmt 的解决方案,只需确保在您的查询中也使用该语法(转换为UTC) - 否则它不会使用索引。谢谢你的把戏。 ;)
  • 根据 thaddeusmt 的建议创建索引可以正常工作。这对我来说是解决方案的一半。查询数据的时候,这里找到了另一半的解决方案。 gist.github.com/cobusc/5875282。以其他人的身份发表评论也可能需要建议。
猜你喜欢
  • 2015-06-27
  • 2016-03-21
  • 1970-01-01
  • 2012-05-23
  • 1970-01-01
  • 2014-10-27
  • 1970-01-01
  • 1970-01-01
  • 2022-01-10
相关资源
最近更新 更多