postgres 综合性能
Posted
技术标签:
【中文标题】postgres 综合性能【英文标题】:postgres aggregate performance 【发布时间】:2012-02-15 05:13:40 【问题描述】:我注意到 Postgres (8.3) 中的简单聚合性能存在一些问题。问题是,如果我有一个由 (customer_id,order_id) 唯一的表(比如 200M 行),那么查询 select customer_id,max(order_id) from larger_table group by customer_id
比执行以下操作的简单 Java/JDBC 程序慢一个数量级以上:
1) 初始化一个空的 HashMap customerMap(这将映射 id -> max order size) 2) 执行“select customer_id,order_id from large_table”,得到一个流式结果集 3) 遍历结果集,在每一行执行如下操作:
long id = resultSet.getLong("customer_id");
long order = resultSet.getLong("order_id");
if (!customerMap.containsKey(id))
customerMap.put(id,order);
else
customerMap.put(id,Math.max(order,customerMap.get(id)));
这种性能差异是预期的吗?我不应该这么想,因为我想上面的内容非常接近内部发生的事情。是否有证据表明数据库存在错误/不正确的调整?
【问题讨论】:
请在您的声明中包含EXPLAIN ANALYZE
的输出,以便我们查看您是否缺少索引。
【参考方案1】:
可能是您的work_mem
设置太低。我会先检查一下。我最近被这个咬了。第二个最可能的问题是您缺少外键索引。
接下来是展览。
一般来说,当数据库性能看起来低于标准时,需要问几个问题:
-
您使用的是最新版本吗? 7.4 和 9.0 之间的每个版本都带来了显着的性能改进 - 如果可以升级,建议升级。
您是否在真实数据上运行基准测试? PostgreSQL 的查询计划器将在同一张表上生成不同的计划,其中包含不同的数据或不同数量的数据。确保始终使用真实数据进行测试。
您的 PostgreSQL 配置是怎样的?
work_mem
开箱即用的设置很低,我自己也遇到过涉及 GROUP BY
的情况,它人为地选择了错误的计划,因为它根本认为它没有足够的工作内存来对结果进行排序。李>
您的 Java 代码是否与数据库在同一台机器上运行?如果不是,您可能会看到计算机之间的差异,而不是方法之间的差异。
您是否缺少索引? PostgreSQL 不会自动为外键创建索引,只为主键创建索引。我也被这个咬过,但是如果你在周围搜索一下,你可以找到一个脚本来检测和添加丢失的外键索引。
在不检查查询计划的情况下,事后猜测 PostgreSQL 为给定查询选择了什么实施策略并不是一个好主意。
【讨论】:
work_mem
的附录:与 JVM 默认分配的内存相比,默认设置低得离谱。如果 Java 可以将所有 (customer,max_order_id)
元组保留在内存中,但 PostgreSQL 不能……那将是一场非常不公平的游戏。 ;-)以上是关于postgres 综合性能的主要内容,如果未能解决你的问题,请参考以下文章