【发布时间】:2017-05-24 14:21:46
【问题描述】:
问题:查询 1 在“语义上”与查询 2 有何不同?
背景:
- 从我本地时区(AT TIME ZONE 'America/New_York')的数据库中的表中提取数据。
- 该表包含不同时区的数据,例如“America/Los_Angeles”、America/North_Dakota/New_Salem 和此类时区。 (Postgres 将不同时区的表数据存储在我的本地时区中)
- 因此,每次我检索本地时间以外的其他位置的数据时,我都会将其转换为相关时区以进行评估..
查询 1:
test_db=# select count(id) from click_tb where date::date AT TIME ZONE 'America/Los_Angeles' = '2017-05-22'::date AT TIME ZONE 'America/Los_Angeles';
count
-------
1001
(1 row)
查询 2:
test_db=# select count(id) from click_tb where (date AT TIME ZONE 'America/Los_Angeles')::date = '2017-05-22'::date;
count
-------
5
(1 row)
表结构:
test_db=# /d+ click_tb
Table "public.click_tb"
Column | Type | Modifiers | Storage | Stats target | Description
-----------------------------------+--------------------------+-------------------------------------------------------------+----------+--------------+-------------
id | integer | not null default nextval('click_tb_id_seq'::regclass) | plain | |
date | timestamp with time zone | | plain | |
Indexes:
"click_tb_id" UNIQUE CONSTRAINT, btree (id)
"click_tb_date_index" btree (date)
查询 1 和查询 2 不会产生一致的结果。
根据我的测试,以下查询 3 在语义上满足了我的要求。
欢迎您提出批评意见。
查询 3:
test_db=# select count(id) from click_tb where ((date AT TIME ZONE 'America/Los_Angeles')::timestamp with time zone)::date = '2017-05-22'::date;
【问题讨论】:
-
第一个问题:为什么不将所有时间信息保存在 UTC 中,并带有一个表示该元组时区的附加字段?
-
任何关系数据库的一般规则:永远不要在 where 子句中对表的字段使用函数。它将使您的查询non-sargable,这意味着它不能使用索引,因此它将扫描整个表,将您的函数应用于每一行。这对性能非常不利,尤其是在大型表上。
-
@MattJohnson:除非您使用该(函数)表达式创建索引。
标签: postgresql datetime etl postgresql-9.3 timestamp-with-timezone