我有一个300万行和1.3GB大小的表 . 在我的笔记本电脑上使用4GB RAM运行Postgres 9.3 .
explain analyze
select act_owner_id from cnt_contacts where act_owner_id = 2
我在cnt_contacts.act_owner_id上有btree键,定义如下:
CREATE INDEX cnt_contacts_idx_act_owner_id
ON public.cnt_contacts USING btree (act_owner_id, status_id);
查询在大约5秒内运行
Bitmap Heap Scan on cnt_contacts (cost=2598.79..86290.73 rows=6208 width=4) (actual time=5865.617..5875.302 rows=5444 loops=1)
Recheck Cond: (act_owner_id = 2)
-> Bitmap Index Scan on cnt_contacts_idx_act_owner_id (cost=0.00..2597.24 rows=6208 width=0) (actual time=5865.407..5865.407 rows=5444 loops=1)
Index Cond: (act_owner_id = 2)
Total runtime: 5875.684 ms"
为什么要这么久?
work_mem = 1024MB;
shared_buffers = 128MB;
effective_cache_size = 1024MB
seq_page_cost = 1.0 # measured on an arbitrary scale
random_page_cost = 15.0 # same scale as above
cpu_tuple_cost = 3.0
2 回答
您正在笔记本电脑上选择分散在1.3 GB表中的5444条记录 . 你期待多长时间?
看起来你的索引没有被缓存,因为它无法在缓存中维持,或者因为这是你第一次使用它的那一部分 . 如果重复运行完全相同的查询会发生什么?相同的查询,但具有不同的常量?
在“explain(analyze,buffers)”下运行查询将有助于获取其他信息,尤其是在您首先启用track_io_timing时 .
好的,PG有大表,索引和长时间执行 . 让我们思考如何改善计划和减少时间的方法 . 您编写和删除行 . PG写和删除元组,表和索引可以膨胀 . 为了良好的搜索,PG将索引加载到共享缓冲区并且您需要尽可能保持索引清洁 . 选择PG读取共享缓冲区而不是搜索 . 尝试设置缓冲区内存并减少索引和表膨胀,保持数据库清理 .
你做了什么,想一想:
1)只检查索引重复项,并且索引具有良好的选择:
2)检查表格和索引是否膨胀?
3)你是否从硬盘清理未使用的元组?真空时间到了吗?
4)想一想 . 如果db中有10条记录,10条中有8条id = 2,那就意味着你的索引选择性很差,这样PG就会扫描所有8条记录 . 但是你尝试使用id!= 2 index会很好用 . 尝试设置具有良好选择的索引 .
5)使用适当的列类型获取数据 . 如果你可以为你的列使用更少的kb类型,只需转换它 .
6)检查数据库和条件 . 检查这个以便开始page只是尝试看到表中有数据库中未使用的数据,必须清理索引,检查索引的选择性 . 尝试使用其他brin索引获取数据,尝试重新创建索引 .