Postgresql 以这样的方式优化表和sql查询,以快速获取两个时间戳之间的数据
我有下表模式Postgresql 以这样的方式优化表和sql查询,以快速获取两个时间戳之间的数据,postgresql,Postgresql,我有下表模式 Table "public.funnel" Column | Type | Modifiers -----------------+-----------------------------+----------- flow | character varying(20) | flowid | character varying(10
Table "public.funnel"
Column | Type | Modifiers
-----------------+-----------------------------+-----------
flow | character varying(20) |
flowid | character varying(100) |
action0 | character varying(50) |
generation_time | timestamp without time zone |
action1 | character varying(50) |
Indexes:
"uniq_flow" UNIQUE CONSTRAINT, btree (flow, flowid)
"idx_analytics_funnel" btree (action0, generation_time)
经常运行的查询是
select count(distinct flowid)
from funnel where flow = ?
and generation_time>=?
and generation_time<=?
and action1 is not null;
通常,当我第一次运行查询时,需要大约40秒的时间。在以后执行的后续查询中,返回结果的时间要短得多。我如何优化它,以便即使在第一次执行时,结果也能快速返回??数据的添加和重组能否带来更好的结果?如果是,需要做什么样的改变
explain analyze execute返回以下结果
QUERY PLAN
----------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------
Aggregate (cost=1115.07..1115.08 rows=1 width=52) (actual time=199.363..199.363 rows=1 loops=1)
-> Bitmap Heap Scan on analytics_funnel (cost=45.23..1114.88 rows=74 width=52) (actual time=119.442..197.196 rows=456 loops=1)
Recheck Cond: ((flow)::text = 'Payments'::text)
Filter: ((action1 IS NOT NULL) AND (generation_time >= '2014-10-20 19:32:23.667'::timestamp without time zone) AND (generation_time <= '2014-10-21 19:32:23.667'::timestamp without time zone))
-> Bitmap Index Scan on uniq_flow (cost=0.00..45.21 rows=657 width=0) (actual time=114.804..114.804 rows=635 loops=1)
Index Cond: ((flow)::text = 'Payments'::text)
Total runtime: 216.328 ms
(7 rows)
您可以尝试的一件事是从生成时间开始的覆盖索引 覆盖索引意味着索引包含解析查询所需的所有字段。覆盖索引只起作用 如果索引从生成时间开始,数据库可以查找而不是扫描到第一行
create index IX_funnel_generation_time on funnel
(generation_time, flow, flowid, action1);
您可以通过运行explain analyze来验证覆盖概念是否有效。如果它工作正常,查询将通过使用IX_漏斗生成时间进行索引扫描来满足。如果它使用了另一个索引或Seq扫描,它就不能正常工作。确切地说,它是哪种RDBMS?看起来像MySQL…我们需要更多细节。表中有多少行?“flow”的典型值有多少行?查询通常返回多少行?action1不为null的频率有多高?缺少这些信息,我会考虑创建一个关于流、生成时间的索引,并且,如果你有一些停机时间,可能会将表聚集在流、生成时间上。然而,如果第一个查询很慢,那么您真的应该发布“解释分析”的结果,但是其他的!查询速度加快后不久,这意味着它必须进行表扫描并从磁盘获取所有数据,然后这些数据会在内存中驻留一段时间,显然存在一个空白,即您不查询此类内容,它会再次从内存中删除。如果该内存是postgresql内存或基于操作系统的磁盘缓存,我无法从这里判断。除了没有用于此查询的有用索引之外,这是另一种攻击。为什么会从记忆中删除?内存争用会增加更多/上限,还是对数据本身的更改太多?