Mil*_*son 4 postgresql performance execution-plan postgresql-9.3 query-performance
给定一个vp
具有列timestamp
类型的表bigint
和一个btree
索引timestamp
,为什么 Postgres 会忽略索引并在timestamp
与浮点值比较时运行 seq 扫描,当索引扫描会产生相同的结果时?
SELECT * FROM vp WHERE vp.timestamp > 1470752584
需要48 毫秒:
在 vp 上使用 vp_ts_idx 进行索引扫描(cost=0.57..257.87 rows=2381 width=57)(实际时间=0.014..38.669 rows=80323 loops=1) 索引条件:(“时间戳”> 1470752584) 总运行时间:48.322 毫秒
SELECT * FROM vp WHERE vp.timestamp > 1470752584.1
需要103 秒,因为它忽略vp_ts_idx
并执行整个表的 seq 扫描:
vp 上的 Seq Scan (cost=0.00..7378353.16 rows=95403915 width=57) (实际时间=62625.420..103122.701 rows=98240 loops=1) 过滤器:(("timestamp")::numeric > 1470752584.1) 过滤器删除的行:285945491 总运行时间:103134.333 毫秒
背景:相比于最近的车辆位置查询timestamp
用EXTRACT(EPOCH FROM NOW()) - %s
,其中%s
为所需的秒数,但没有明确铸造到bigint
。解决方法是使用CAST(EXTRACT(EPOCH FROM NOW()) - %s AS bigint)
.
当列类型为 时,为什么查询计划器不会自动执行此操作bigint
?这是一个错误,还是我没有考虑这种行为有用的一些边缘情况?
关键是你不要比较相同的类型。将 abigint
与 a进行比较时numeric
,更简单的方法是“扩展”bigint
小数位为 0(如 1 -> 1.0),而反之则意味着四舍五入/截断。(在这种特定情况下,很容易看出两者导致相同的结果,但如果值为负呢?)
那么,是什么在您的比较得到的,是numeric
要numeric
比较,这是不是一个bigint
指数可以食用。
值得一看的是,哪些类型转换是可能的,哪些是在这些情况下执行的。为此,这里有两行pg_cast
:
SELECT castsource::regtype, casttarget::regtype, castcontext
FROM pg_cast
WHERE castsource::regtype = 'bigint'::regtype
AND casttarget::regtype = 'numeric'::regtype;
castsource ? casttarget ? castcontext
???????????????????????????????????????
bigint ? numeric ? i
SELECT castsource::regtype, casttarget::regtype, castcontext
FROM pg_cast
WHERE castsource::regtype = 'numeric'::regtype
AND casttarget::regtype = 'bigint'::regtype;
castsource ? casttarget ? castcontext
???????????????????????????????????????
numeric ? bigint ? a
Run Code Online (Sandbox Code Playgroud)
根据链接的文档页面, castcontext
指示可以在哪些上下文中调用强制转换。
e
仅表示显式强制转换(使用CAST
或::
语法)。a
意味着隐式分配给目标列,以及显式。i
意味着隐含在表达式中,以及其他情况。
因此,这意味着numeric
->bigint
方向仅在您将前者分配给后者时才“自行”发生(即您没有显式调用其中一个转换运算符)。在像您的比较这样的表达式中,情况并非如此,因此解析器只会考虑另一种方式(用i
上面标记)。这意味着,除非您以其他方式强制numeric
进行numeric
比较,否则您可以进行比较。
笔记:
psql
是 PostgreSQL 的命令行客户端,它本身不做任何这些事情(我已经相应地编辑了标题)timestamp
)从来都不是一个好主意 - 你可能会在这里和那里遇到意想不到的解析错误,除非你足够小心,在任何地方都用双引号引起来 归档时间: |
|
查看次数: |
1417 次 |
最近记录: |