我在Ubuntu 12.04上使用PostgreSQL 9.1。
我需要选择一段时间内的记录:我的表time_limits
有两个timestamp
字段和一个integer
属性。我的实际表中还有其他列不涉及此查询。
create table (
start_date_time timestamp,
end_date_time timestamp,
id_phi integer,
primary key(start_date_time, end_date_time,id_phi);
该表包含大约2M条记录。
进行以下查询需要花费大量时间:
select * from time_limits as t
where t.id_phi=0
and t.start_date_time <= timestamp'2010-08-08 00:00:00'
and t.end_date_time >= timestamp'2010-08-08 00:05:00';
所以我尝试添加另一个索引-PK的倒数:
create index idx_inversed on time_limits(id_phi, start_date_time, end_date_time);
我感觉性能有所提高:访问表中间的记录的时间似乎更合理:介于40到90秒之间。
但是对于时间范围的中间值,仍然需要数十秒的时间。定位到表格末尾时(按时间顺序),则要多两倍。
我explain analyze
第一次尝试获取此查询计划:
Bitmap Heap Scan on time_limits (cost=4730.38..22465.32 rows=62682 width=36) (actual time=44.446..44.446 rows=0 loops=1)
Recheck Cond: ((id_phi = 0) AND (start_date_time <= '2011-08-08 00:00:00'::timestamp without time zone) AND (end_date_time >= '2011-08-08 00:05:00'::timestamp without time zone))
-> Bitmap Index Scan on idx_time_limits_phi_start_end (cost=0.00..4714.71 rows=62682 width=0) (actual time=44.437..44.437 rows=0 loops=1)
Index Cond: ((id_phi = 0) AND (start_date_time <= '2011-08-08 00:00:00'::timestamp without time zone) AND (end_date_time >= '2011-08-08 00:05:00'::timestamp without time zone))
Total runtime: 44.507 ms
我该怎么做才能优化搜索?你可以看到所有的时间都花在扫描两个时间戳列一旦id_phi
设置为0
。而且我不了解时间戳上的大扫描(60K行!)。他们不是通过主键索引的idx_inversed
吗?
我应该从时间戳类型更改为其他类型吗?
我已经阅读了一些有关GIST和GIN索引的信息。我收集到,在某些情况下,对于自定义类型它们可以更有效。我的用例是否可行?
explain analyze
输出中报告的时间是服务器上查询所需的时间。如果您的查询花了45秒,那么将花费额外的时间将数据从数据库传输到运行查询的程序中。毕竟它是62682行,并且如果每行很大(例如长varchar
或多text
列),这可能会影响传输时间剧烈地。
rows=62682 rows
是计划者的估计。查询返回0行。(actual time=44.446..44.446 rows=0 loops=1)