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
。
在整个索引tab1
,tab2
和tab4
上的结果被扫描,使缓存混乱。
尝试增加您的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
您是否实际上每次都在阅读整个视图,而没有任何过滤?如果这意味着你在应用程序中进行筛选,那么你应该将它们作为WHERE子句进行推送。如果你正在使用WHERE子句进行操作,并且没有将它包含在这里的帖子中,那么你需要重新发布包括:-)
如果你每次都在阅读整件事,那么是的,并非全部你可以对此做很多事情。正如先前评论过的,增加你的shared_buffers使得所有的东西都适合(它似乎是一个小的数据库)。
该计划看起来有点奇怪 - 确切地说你更改了哪些配置参数,以及什么?
我做了过滤。如果我这样做,不要花那么长时间,但我的道具不是那个问题。我的问题是,当我查询数据库上的很多人时,它会花费很长时间。我不知道数据库如何工作,但我认为postgres打开10个进程,evry进程查询我的视图。所以我不必等到每个过程完成。你知道我的意思? – Nico 2010-02-01 17:13:04
正如您所说,您在问题中显示的单个查询不是真正的问题。
解决它之前,您必须检测到真正的问题。“10个连接需要很长时间”还不够。
说明你发布的内容是无用的 - 用WHERE条件显示真正的查询。 时间(在解释分析输出)只证明你的服务器目前只是过载。查询40k行5秒钟? - 这真的很悲惨。
您需要检测消耗大部分服务器资源的查询。 要做到这一点,请使用类似pgfouine的工具来执行工作负载统计。它需要一些时间,但它是值得的。
我还会在猜测之前查看系统统计信息(IO使用情况,内存,CPU)。
如果这将是一个生产服务器,请设置一个监控工具 - 如果您还没有。我建议使用munin,在15分钟内很容易启动并运行(为某些Linux发行版打包)。
正如我评论上面这个查询是不是孔洞。我的问题是,当我查询数据库上的很多人时,它会花费很长时间。我不知道数据库如何工作,但我认为postgres打开10个进程,evry进程查询我的视图。所以我不必等到每个过程完成。 明天我告诉你结果。我现在没有足够的时间:/ – Nico 2010-02-01 17:15:18