postgresql - 在没有时区字段的时间戳上查询不使用索引
问题描述
我有一个超过 300 万行的表,其中一列creationdate
名为timestamp without time zone
.
我在上面创建了几个索引,例如:
"idx_routingtasks_creationdate" btree (creationdate)
"idx_routingtasks_creationdate2" btree ((creationdate::date))
creationdate::date
当按(按日期转换)过滤时,idx_routingtasks_creationdate
不使用索引:
explain analyze select * from routingtasks where creationdate::date < (now() - interval '1 day')::date;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------
Seq Scan on routingtasks (cost=0.00..1315631.93 rows=2811638 width=715) (actual time=186642.012..413763.643 rows=2800659 loops=1)
Filter: ((creationdate)::date < ((now() - '1 day'::interval))::date)
Rows Removed by Filter: 212248
Planning time: 0.195 ms
Execution time: 413875.829 ms
(5 rows)
不按日期投射时也是如此:
explain analyze select * from routingtasks where creationdate < now() - interval '1 day';
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------
Seq Scan on routingtasks (cost=0.00..1300588.39 rows=2918447 width=715) (actual time=72089.312..327288.333 rows=2876756 loops=1)
Filter: (creationdate < (now() - '1 day'::interval))
Rows Removed by Filter: 141052
Planning time: 0.104 ms
Execution time: 327401.745 ms
(5 rows)
如何在creationdate
列上创建索引以允许此过滤器使用它?
解决方案
答案就在执行计划的这一部分:
Seq Scan ... (actual ... rows=2876756 ...)
...
Rows Removed by Filter: 141052
由于无论如何都会返回几乎所有行,因此使用顺序扫描并丢弃过滤掉的少数行是处理查询的最有效方法。
如果你想验证,暂时
SET enable_seqscan = off;
如果可能,使 PostgreSQL 避免顺序扫描。然后您可以测试查询执行是否变得更快。
推荐阅读
- python - Pandas dtype=datetime64[ns] 和日期错误
- sql - Pony ORM 中的动态分组 -> 聚合
- json - MongoDB:分别对每个文档上的嵌套数组进行排序
- android - 资产包无法指定版本代码,但“基础”可以,我做错了什么?
- mongodb - Mongoose Schema 如何映射到 MongoDB 中的集合?
- linux - fork()之后,如何防止子进程读取不必要的数据?
- android - requestLocationUpdates 在模拟器上不起作用
- node.js - 是否可以在网络流量中不可见的情况下将数据从服务器发送到客户端?
- javascript - 通过jquery字符串连接多个变量
- node.js - 使用 NPM 搜索包时出现“无法读取未定义的属性'插入'”