4

我注意到 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 -> 最大订单大小) 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)));

这种性能差异是预期的吗?我不应该这么想,因为我想上面的内容非常接近内部发生的事情。是否有证据表明数据库存在错误/错误调整?

4

1 回答 1

6

可能是你的work_mem设置太低了。我会先检查一下。我最近被这个咬了。第二个最可能的问题是您缺少外键索引。

博览会紧随其后。

一般来说,当数据库性能看起来低于标准时,需要问几个问题:

  1. 您使用的是最新版本吗?7.4 和 9.0 之间的每个版本都带来了显着的性能改进——如果可以升级,建议使用。
  2. 您是否在真实数据上运行基准测试?PostgreSQL 的查询计划器将在同一张表上生成不同的计划,其中包含不同的数据或不同数量的数据。确保您始终使用真实数据进行测试。
  3. 你的 PostgreSQL 配置是什么样的?work_mem开箱即用的设置很低,我自己也遇到GROUP BY过人为选择错误计划的情况,因为它根本认为它没有足够的工作记忆来对结果进行排序。
  4. 您的 Java 代码是否与数据库在同一台机器上运行?如果没有,您可能会看到计算机之间的差异,而不是方法之间的差异。
  5. 您是否缺少索引?PostgreSQL 不会自动为外键创建索引,只为主键创建索引。我也被这个咬过,但是如果你在周围搜索一下,你可以找到一个脚本来检测和添加丢失的外键索引。

在不检查查询计划的情况下,事后猜测 PostgreSQL 为给定查询选择了什么实现策略并不是一个好主意。

于 2012-02-15T05:26:05.217 回答