postgres查询性能设置

postgres查询性能设置

问题描述:

我有一个web应用程序,执行大约33.000行postgresql视图上的搜索。如果我单独尝试,大约需要1-2秒才能得到结果,这是我首先想到的。但后来我从微软下载了Web应用程序压力测试工具,以便在我的webapp上加载一些内容。所以我首先尝试了10个并发“用户”。当测试运行时,我执行搜索需要更长的时间,我必须等待大约10-20秒才能得到我的结果,这是我认为不可接受的。因为我是洞穴数据库(Postgresql)的新手,所以在过去的3-4天里我阅读了很多,但是我无法更快地完成搜索表现。我改变了一些配置设置,比如work_mem,shared_buffer等等,但是它并没有变好。postgres查询性能设置

所以我的问题是:任何人都可以给我提示什么我可以改变我的配置或我的服务器,以获得更好的性能,而不是十个并发用户?

以下是有关服务器和浏览一些细节:

服务器(virual机):

3 GHZ Xeon 
3 GB Ram 
40 GB Harddrive 

视图的Select语句看起来是这样的:

SELECT my selects, .... 
FROM tab1 
JOIN tab2 ON tab1.index1 = tab2.index1 
JOIN tab3 ON tab1.index0 = tab3.index0 
JOIN tab4 ON tab1.index1 = tab4.index1; 

我设置每个索引1和索引0上的索引。

的解释(默认postgres.conf)分析:

EXPLAIN ANALYZE SELECT * from view_myview; 

Nested Loop (cost=0.90..29042.71 rows=49840 width=1803) (actual time=0.384..5380.477 rows=33620 loops=1) 
-> Merge Join (cost=0.90..11740.81 rows=24403 width=1257) (actual time=0.263..2548.377 rows=22601 loops=1) 
    Merge Cond: (tab2.index1 = tab1.index1) 
    -> Merge Join (cost=0.00..7170.63 rows=15968 width=1251) (actual time=0.157..1225.752 rows=15968 loops=1) 
      Merge Cond: (tab2.index1 = tab4.index1) 
      -> Index Scan using tab2_index1_idx on tab2 (cost=0.00..3617.45 rows=15968 width=1025) (actual time=0.053..239.399 rows=15968 loops=1) 
      -> Index Scan using tab4_index1_idx on tab4 (cost=0.00..3310.83 rows=17103 width=226) (actual time=0.045..253.721 rows=17103 loops=1) 
    -> Index Scan using tab1_index1_0_idx on tab4 (cost=0.00..4226.13 rows=24403 width=50) (actual time=0.051..347.333 rows=24403 loops=1) 
-> Index Scan using tab3_index0_idx on tab3 (cost=0.00..0.64 rows=2 width=568) (actual time=0.030..0.050 rows=1 loops=22601) 
    Index Cond: (tab3.index0 = tab1.index0) 
Total runtime: 5814.165 ms 

希望有人能帮助,

尼科

这是一个明星的查询,但由于某种原因PostgreSQL决定使用尺寸表之间的距离为MERGE JOIN

在整个索引tab1tab2tab4上的结果被扫描,使缓存混乱。

尝试增加您的shared_buffer,使所有三个指标适合那里。

另外,您可以请发布以下查询的结果吗?

SELECT COUNT(*) 
FROM tab2 
JOIN tab4 
ON  tab2.index1 = tab4.index1 

SELECT COUNT(*) 
FROM tab2 
JOIN tab4 
ON  tab2.index1 = tab4.index1 
JOIN tab1 
ON  tab1.index1 = tab4.index1 

SELECT COUNT(*) 
FROM tab1 
JOIN tab3 
ON  tab3.index0 = tab1.index0 

SELECT COUNT(*) 
FROM tab1 
JOIN tab4 
ON  tab1.index1 = tab4.index1 

SELECT COUNT(*) 
FROM tab1 
JOIN tab2 
ON  tab1.index1 = tab2.index1 
+0

正如我评论上面这个查询是不是孔洞。我的问题是,当我查询数据库上的很多人时,它会花费很长时间。我不知道数据库如何工作,但我认为postgres打开10个进程,evry进程查询我的视图。所以我不必等到每个过程完成。 明天我告诉你结果。我现在没有足够的时间:/ – Nico 2010-02-01 17:15:18

您是否实际上每次都在阅读整个视图,而没有任何过滤?如果这意味着你在应用程序中进行筛选,那么你应该将它们作为WHERE子句进行推送。如果你正在使用WHERE子句进行操作,并且没有将它包含在这里的帖子中,那么你需要重新发布包括:-)

如果你每次都在阅读整件事,那么是的,并非全部你可以对此做很多事情。正如先前评论过的,增加你的shared_buffers使得所有的东西都适合(它似乎是一个小的数据库)。

该计划看起来有点奇怪 - 确切地说你更改了哪些配置参数,以及什么?

+0

我做了过滤。如果我这样做,不要花那么长时间,但我的道具不是那个问题。我的问题是,当我查询数据库上的很多人时,它会花费很长时间。我不知道数据库如何工作,但我认为postgres打开10个进程,evry进程查询我的视图。所以我不必等到每个过程完成。你知道我的意思? – Nico 2010-02-01 17:13:04

正如您所说,您在问题中显示的单个查询不是真正的问题。

解决它之前,您必须检测到真正的问题。“10个连接需要很长时间”还不够。

说明你发布的内容是无用的 - 用WHERE条件显示真正的查询。 时间(在解释分析输出)只证明你的服务器目前只是过载。查询40k行5秒钟? - 这真的很悲惨。

您需要检测消耗大部分服务器资源的查询。 要做到这一点,请使用类似pgfouine的工具来执行工作负载统计。它需要一些时间,但它是值得的。

我还会在猜测之前查看系统统计信息(IO使用情况,内存,CPU)。

如果这将是一个生产服务器,请设置一个监控工具 - 如果您还没有。我建议使用munin,在15分钟内很容易启动并运行(为某些Linux发行版打包)。