Postgres timestamptz 列和用户的时区
Postgres timestamptz column and user's timezone
将 table 更改为对所有时间列使用 timestamptz 后,我看到在根据时间范围执行 select 时出现非常奇怪的行为。当用户的时区是 UTC 时,它工作,结果是正确的。当用户的时区不是 UTC 时,结果为零。我希望结果不应该取决于用户的时区。
set timezone = 'UTC';
select count(*)
from table1
where modified >= timestamp '2016-07-25 08:00' at time zone 'GB'
and modified < timestamp '2016-07-25 09:00' at time zone 'GB'
;
set timezone = 'GB';
select count(*)
from table1
where modified >= timestamp '2016-07-25 08:00' at time zone 'GB'
and modified < timestamp '2016-07-25 09:00' at time zone 'GB'
;
在查询解释中,我看到 Postgres 正确地转换了时间常数。在第一种情况下 (UTC) 它显示
'2016-07-25 07:00:00+00'::timestamp with timezone
'2016-07-25 08:00:00+00'::timestamp with timezone
第二种情况 (GB) 显示
'2016-07-25 08:00:00+01'::timestamp with timezone
'2016-07-25 09:00:00+01'::timestamp with timezone
更奇怪的是,只有时差为一小时时,它才完全不工作。当我过滤两个小时,从早上 8 点到上午 10 点,查询 returns 个非零结果。它是这样工作的
count(*) from 08:00 to 09:00 - zero
count(*) from 09:00 to 10:00 - zero
count(*) from 08:00 to 10:00 = actual count from 09:00 to 10:00
范围转换似乎存在错误。转换开始时间但不转换结束时间。
我想知道以前是否有人看到过这个问题。 Postgres 是 9.3.4,运行 在 Ubuntu。
modified
列的定义
...
modified timestamp with time zone NOT NULL DEFAULT now(),
...
解释
Aggregate (cost=374.84..374.85 rows=1 width=0)
Output: count(*)
-> Index Only Scan using modified_idx on public.table1 (cost=0.56..362.14 rows=5079 width=0)
Output: modified
Index Cond: ((table1.modified >= '2016-07-25 08:00:00+01'::timestamp with time zone) AND (table1.modified < '2016-07-25 09:00:00+01'::timestamp with time zone))
这似乎是不可能的,想到的唯一解释是索引已损坏。
REINDEX INDEX modified_idx;
将重建索引,希望能解决问题。
将 table 更改为对所有时间列使用 timestamptz 后,我看到在根据时间范围执行 select 时出现非常奇怪的行为。当用户的时区是 UTC 时,它工作,结果是正确的。当用户的时区不是 UTC 时,结果为零。我希望结果不应该取决于用户的时区。
set timezone = 'UTC';
select count(*)
from table1
where modified >= timestamp '2016-07-25 08:00' at time zone 'GB'
and modified < timestamp '2016-07-25 09:00' at time zone 'GB'
;
set timezone = 'GB';
select count(*)
from table1
where modified >= timestamp '2016-07-25 08:00' at time zone 'GB'
and modified < timestamp '2016-07-25 09:00' at time zone 'GB'
;
在查询解释中,我看到 Postgres 正确地转换了时间常数。在第一种情况下 (UTC) 它显示
'2016-07-25 07:00:00+00'::timestamp with timezone
'2016-07-25 08:00:00+00'::timestamp with timezone
第二种情况 (GB) 显示
'2016-07-25 08:00:00+01'::timestamp with timezone
'2016-07-25 09:00:00+01'::timestamp with timezone
更奇怪的是,只有时差为一小时时,它才完全不工作。当我过滤两个小时,从早上 8 点到上午 10 点,查询 returns 个非零结果。它是这样工作的
count(*) from 08:00 to 09:00 - zero
count(*) from 09:00 to 10:00 - zero
count(*) from 08:00 to 10:00 = actual count from 09:00 to 10:00
范围转换似乎存在错误。转换开始时间但不转换结束时间。
我想知道以前是否有人看到过这个问题。 Postgres 是 9.3.4,运行 在 Ubuntu。
modified
列的定义
...
modified timestamp with time zone NOT NULL DEFAULT now(),
...
解释
Aggregate (cost=374.84..374.85 rows=1 width=0)
Output: count(*)
-> Index Only Scan using modified_idx on public.table1 (cost=0.56..362.14 rows=5079 width=0)
Output: modified
Index Cond: ((table1.modified >= '2016-07-25 08:00:00+01'::timestamp with time zone) AND (table1.modified < '2016-07-25 09:00:00+01'::timestamp with time zone))
这似乎是不可能的,想到的唯一解释是索引已损坏。
REINDEX INDEX modified_idx;
将重建索引,希望能解决问题。