我创建了类似的索引
CREATE INDEX bill_open_date_idx ON bill USING btree(date(open_date));
和,
Column | Type
open_date | timestamp without time zone
并解释分析如下
情况1
explain analyze select * from bill where open_date >=date('2018-01-01');
Seq Scan on bill (cost=0.00..345264.60 rows=24813 width=1132) (actual time=0.007..1305.730 rows=5908 loops=1)
Filter: (open_date >= '2018-01-01'::date)
Rows Removed by Filter: 3238812
Total runtime: 1306.176 ms
案例二
explain analyze select * from bill where open_date>='2018-01-01';
Seq Scan on bill (cost=0.00..345264.60 rows=24813 width=1132) (actual time=0.006..1220.697 rows=5908 loops=1)
Filter: (open_date>= '2018-01-01 00:00:00'::timestamp without time zone)
Rows Removed by Filter: 3238812
Total runtime: 1221.131 ms
案例 3
explain analyze select * from bill where date(open_date) >='2018-01-01';
Index Scan using idx_bill_open_date on bill (cost=0.43..11063.18 rows=22747 width=1132) (actual time=0.016..4.744 rows=5908 loops=1)
Index Cond: (date(open_date) >= '2018-01-01'::date)
Total runtime: 5.236 ms
(3 rows)
我对为什么会发生这种情况进行了足够的研究,但是任何地方都没有适当的解释。只有案例 3使用的是我创建的索引,而不是其他的。为什么会这样?
据我了解,案例 2搜索与列等效的字符串open_date
,因此它不使用索引。但是为什么不是案例1。另外,如果我错了,请纠正我。
提前致谢!
编辑1:另外,我很高兴知道深入发生了什么。
以下是要点的摘录(https://gist.github.com/cobusc/5875282)
奇怪的是,PostgreSQL 将用于创建索引的函数重写为规范形式,但在 WHERE 子句中使用该函数时似乎没有这样做(为了匹配索引函数)。
尽管如此,我仍然不清楚为什么 postgres 的开发人员没有考虑获取任何附近的匹配索引(或者我的索引在我明确转换date
为case 3之前是无用的)。考虑到 Postgres 是高度发展和可扩展的。