Простой агрегирующий запрос очень медленный в PostgreSql, какой-нибудь способ улучшить? - PullRequest
2 голосов
/ 25 мая 2010

HI

У меня есть таблица с файлами и их типами, такими как

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 имеет индекс.

Таблица файлов содержит около 800 тыс. Строк, а таблица свойств - около 200 тыс. (Не все файлы обязательно имеют / нуждаются в свойствах).

Я хочу выполнить агрегирование запросов, например, найти средний размер и стандартное отклонение для всех типов файлов. Но это очень медленно - около 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

Есть идеи, почему это так медленно / как сделать это быстрее?

Ответы [ 2 ]

1 голос
/ 25 мая 2010

Определили ли вы разумные настройки для параметров сервера, таких как shared_buffers, work_mem иffective_cache_size? http://wiki.postgresql.org/wiki/Tuning_Your_PostgreSQL_Server

В частности, я думаю, что work_mem повлияет на то, сколько хеш-таблиц для объединения может храниться в памяти, а не на диске. Кроме того, уменьшенное random_page_cost может повлиять на планировщика вместо использования объединения слиянием - попробуйте временно отключить «enable_hashjoin» и посмотреть, дает ли это план, который работает лучше?

1 голос
/ 25 мая 2010

Я не знаю о postgressql, но я бы

  • убедитесь, что filetype имеет индекс, возможно, индекс покрытия для типа файла и идентификатора.
  • попробуйте переписать запрос следующим образом

Оператор 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
...