2014-02-21 121 views
2

我在PGPostgres的缓慢限制查询

EXPLAIN ANALYZE 
select * from email_events 
where act_owner_id = 500 
order by date desc 
limit 500 

这个简单的查询第一个查询的执行需要很长的时间约7秒钟。

"Limit (cost=0.43..8792.83 rows=500 width=2311) (actual time=3.064..7282.497 rows=500 loops=1)" 
" -> Index Scan Backward using email_events_idx_date on email_events (cost=0.43..233667.36 rows=13288 width=2311) (actual time=3.059..7282.094 rows=500 loops=1)" 
"  Filter: (act_owner_id = 500)" 
"  Rows Removed by Filter: 1053020" 
"Total runtime: 7282.818 ms" 

第一次执行后,我猜的查询被缓存,并在20-30毫秒。

为什么LIMIT在没有缓存时很慢?我怎样才能解决这个问题?

+0

该表有2.5 mil行 –

+1

您有关于(act_owner_id,date)的索引吗? – DRapp

+0

是的,即使按照act_owner_id排序,结果也是一样的 –

回答

1

PostgreSQL认为向后扫描日期排序索引(即以DESC的顺序)会更快,读取每一行并丢掉没有正确的act_owner_id的行。它必须做1053020个随机读取操作,而后向索引扫描也不是很快。

尝试在email_events(date DESC, act_owner_id)上创建索引。我认为 Pg将能够做一个正向索引扫描,然后使用第二个索引项来过滤行,所以它不应该做一个堆查找。用EXPLAIN进行测试并参见。

+0

没有帮助......数据库中充满了我生成的虚拟数据,散装表格按表装载......我在一张较小的表格上制作了CLUSTER,问题似乎在该表格中是固定的。在第一次执行查询时,在第一次执行查询后,在500ms内执行查询,在CLUSTER用到20秒之前..将在最大的表上执行CLUSTER以查看是否可以解决问题 –

2

INDEX上的CLUSTER TABLE似乎解决了这个问题。看起来,大容量数据加载后,数据遍布硬盘。 CLUSTER表将重新排序硬盘上的数据

+0

很高兴看到CLUSTER一个索引有用一次。 –