【问题标题】:Simple aggregating query very slow in PostgreSql, any way to improve?PostgreSql 中的简单聚合查询非常慢,有什么改进的方法吗?
【发布时间】:2010-05-25 12:08:32
【问题描述】:

我有一个表格,其中包含文件及其类型,例如

CREATE TABLE files (
    id          SERIAL PRIMARY KEY, 
    name        VARCHAR(255),
    filetype    VARCHAR(255),
    ...
);

和另一个用于保存文件属性的表,例如

CREATE TABLE properties (
    id          SERIAL PRIMARY KEY, 
    file_id     INTEGER CONSTRAINT fk_files REFERENCES files(id),
    size        INTEGER,
    ... // other property fields
);

file_id 字段有一个索引。

文件表大约有 80 万行,属性表大约有 20 万行(并非所有文件都必须具有/需要属性)。

我想做聚合查询,例如查找所有文件类型的平均大小和标准偏差。但它非常慢 - 后一个查询大约需要 70 秒。我知道它需要顺序扫描,但似乎还是太多了。 这是查询

SELECT f.filetype, avg(size), stddev(size) FROM files as f, properties as pr 
 WHERE f.id = pr.file_id GROUP BY f.filetype;

还有解释

 HashAggregate  (cost=140292.20..140293.94 rows=116 width=13) (actual time=74013.621..74013.954 rows=110 loops=1)
   ->  Hash Join  (cost=6780.19..138945.47 rows=179564 width=13) (actual time=1520.104..73156.531 rows=179499 loops=1)
         Hash Cond: (f.id = pr.file_id)
         ->  Seq Scan on files f  (cost=0.00..108365.41 rows=1140941 width=9) (actual time=0.998..62569.628 rows=805270 loops=1)
         ->  Hash  (cost=3658.64..3658.64 rows=179564 width=12) (actual time=1131.053..1131.053 rows=179499 loops=1)
               ->  Seq Scan on properties pr  (cost=0.00..3658.64 rows=179564 width=12) (actual time=0.753..557.171 rows=179574 loops=1)
Total runtime: 74014.520 ms

任何想法为什么它这么慢/如何使它更快?

【问题讨论】:

    标签: sql postgresql aggregate


    【解决方案1】:

    您是否为 shared_buffers、work_mem 和 Effective_cache_size 等服务器参数定义了合理的设置? http://wiki.postgresql.org/wiki/Tuning_Your_PostgreSQL_Server

    特别是,我认为 work_mem 会影响连接的哈希表有多少可以保存在内存中而不是磁盘上。此外,减少的 random_page_cost 可能会影响规划器改为使用合并连接 - 尝试暂时将“enable_hashjoin”设置为关闭,看看是否会产生更好的规划?

    【讨论】:

      【解决方案2】:

      我不知道 postgressql 但我会

      • 确保filetype 有一个索引,可能是文件类型和id 的覆盖索引。
      • 尝试像这样重写查询

      SQL 语句

      SELECT  f.filetype
              , avg_size
              , stddev_size
      FROM    files as f
              INNER JOIN (
                SELECT  file_id
                        , avg(size) as avg_size
                        , stddev(size) as stddev_size
                FROM    properties
                GROUP BY 
                        file_id
              ) p ON p.file_id = f.id
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-03-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-04
        • 2020-03-26
        相关资源
        最近更新 更多