Sql 向带有时区的时间戳添加索引
我想改进这个缓慢的查询,我想添加一个索引,但我不知道哪种索引类型更适合我的情况Sql 向带有时区的时间戳添加索引,sql,postgresql,indexing,count,timezone,Sql,Postgresql,Indexing,Count,Timezone,我想改进这个缓慢的查询,我想添加一个索引,但我不知道哪种索引类型更适合我的情况 SELECT COUNT(*) ct FROM events WHERE dtt AT TIME ZONE 'America/Santiago' >= date(now() AT TIME ZONE 'America/Santiago') + interval '1s' 查询计划: "Aggregate (cost=128032.03..128032.04 rows=1 width=0) (act
SELECT COUNT(*) ct FROM events
WHERE dtt AT TIME ZONE 'America/Santiago'
>= date(now() AT TIME ZONE 'America/Santiago') + interval '1s'
查询计划:
"Aggregate (cost=128032.03..128032.04 rows=1 width=0) (actual time=3929.083..3929.083 rows=1 loops=1)"
" -> Seq Scan on events (cost=0.00..125937.68 rows=837742 width=0) (actual time=113.080..3926.972 rows=25849 loops=1)"
" Filter: (timezone('America/Santiago'::text, dtt) >= (date(timezone('America/Santiago'::text, now())) + '00:00:01'::interval))"
" Rows Removed by Filter: 2487386"
"Planning time: 0.179 ms"
"Execution time: 3929.136 ms"
- 该查询获取当天事件的计数
- dtt是带有时区列的时间戳
- 我正在使用Postgresql 9.4
"Aggregate (cost=119667.76..119667.77 rows=1 width=0) (actual time=3687.151..3687.152 rows=1 loops=1)"
" -> Seq Scan on vehicle_events (cost=0.00..119667.14 rows=250 width=0) (actual time=104.635..3687.068 rows=469 loops=1)"
" Filter: (dtt >= timezone('America/Santiago'::text, date_trunc('day'::text, timezone('America/Santiago'::text, now()))))"
" Rows Removed by Filter: 2513337"
"Planning time: 0.164 ms"
"Execution time: 3687.204 ms"
首先,修复查询以生成谓词: 按原样使用列值并将所有计算移动到参数 没错,在导出一天的本地开始时间后,再次在时区应用
,将时间戳
转换回时间戳
。详情:
逐步解释
now()
.. 是SQL标准的Postgres实现当前时间戳
。两者都是100%等效的,您可以使用其中一种。它将当前时间点返回为timestamtz
——该值的显示考虑了当前会话的时区,但这与该值无关
now()
在时区“美国/圣地亚哥”
.. 计算给定时区的本地时间。结果数据类型为时间戳。我们这样做是为了:
date\u trunc(
now()在时区“美国/圣地亚哥”
)
.. 截断时间分量以获取“America/Santiago”中的本地一天开始时间,与当前时区设置无关
date\u trunc('day',now()在时区“America/Santiago”)
在时区“America/Santiago”
.. 将时间戳
输入时区的构造,我们得到相应的时间戳
值(UTC内部),以比较时间戳
值dtt
我删除了+间隔'1s'
,怀疑您刚刚滥用它将日期
转换为时间戳
。使用date\u trunc()
生成时间戳
值
现在,dtt
上的普通(默认)btree索引就可以了。当然,只有当谓词具有足够的选择性时,才会使用索引
CREATE INDEX events_dtt_idx ON events (dtt);
如果您的重要查询只考虑最近的行,则<强>部分索引< /强>可能会有帮助。详情:
谢谢Erwin的回答,我现在有了一个更好的结果,但是查询速度仍然很慢,需要对我的表重新编制索引吗?@Goku:reindex
只有在索引严重膨胀或损坏时才需要<代码>真空分析事件
可能有助于为您提供一个解决方案。如果由于太多的写入活动而无法获得仅索引扫描,则对表进行集群可能会加快扫描速度。您忘记转换回UTC了吗?或者这是在比较中隐含的吗?@Matt:都不是。“转换为UTC”是转换为timestamptz
的一个隐含细节,它是UTC内部时间戳,独立于时区工作。请不要被有点误导性的数据类型名称弄糊涂:。按照链接查看详细信息。@MattJohnson:No.date\u trunc()
返回timestamp
输入的timestamp
和timestamp
输入的timestamp
。为了澄清,我一步一步地添加了一个解释。吹毛求疵,你的查询不会“得到当天事件的数量”。它获取从一天开始的所有事件的计数-包括将来的时间戳(如果有),这可能很容易在多个时区发生。
CREATE INDEX events_dtt_idx ON events (dtt);