Улучшение алгоритма на простом запросе postgresql - PullRequest
5 голосов
/ 02 июля 2010

Высокий уровень : Могу ли я сделать это order by, group by на основе sum еще быстрее?(PG 8.4, fwiw., На не крошечной таблице .... думаю, O (миллионы строк))

Предположим, у меня была такая таблица:

                                 Table "public.summary"
   Column    |       Type        |                      Modifiers
-------------+-------------------+------------------------------------------------------
 ts          | integer           | not null default nextval('summary_ts_seq'::regclass)
 field1      | character varying | not null
 otherfield  | character varying | not null
 country     | character varying | not null
 lookups     | integer           | not null


Indexes:
    "summary_pk" PRIMARY KEY, btree (ts, field1, otherfield, country)
    "ix_summary_country" btree (country)
    "ix_summary_field1" btree (field1)
    "ix_summary_otherfield" btree (otherfield)
    "ix_summary_ts" btree (ts)

Изапрос, который я хочу:

select summary.field1,
    summary.country,
    summary.ts,
    sum(summary.lookups) as lookups,
from summary
where summary.country = 'za' and
    summary.ts = 1275177600
group by summary.field1, summary.country, summary.ts
order by summary.ts, lookups desc, summary.field1
limit 100;

(на английском языке: 100 лучших полей1 в определенном месте (ts, страна), где 'topness' - это сумма поисков для любой подходящей строки независимо от значения другого поля)

Есть ли что-нибудь , что я действительно могу сделать, чтобы ускорить это?С алгоритмической точки зрения это похоже на сканирование всей таблицы, но я могу что-то упустить.

Ответы [ 3 ]

2 голосов
/ 02 июля 2010

Любой план запроса для этого запроса должен будет сканировать каждую строку, которая соответствует условиям WHERE, сворачивая их по условиям группировки, то есть объем работы пропорционален количеству входных строк для группы, а не количество строк результата.

Наиболее эффективный план запроса, возможный для такого запроса, - это сканирование по одному индексу. Это должно быть возможно, если вы строите индекс (страна, ts) в этом порядке; с этим индексом каждый возможный запрос этой формы разрешается в непрерывный диапазон по индексу. Тем не менее, для этого потребуется сортировка в памяти - этого можно избежать с другим индексом.

Как уже говорили другие, размещение плана выполнения является вашим лучшим вариантом.

1 голос
/ 02 июля 2010

Индекс на (страна, ts) - лучшая ставка (как предлагает Ник Джонсон), и дополнительно вы можете поднять work_mem , если он не установлен слишком высоко. Вы можете установить это во время выполнения, если это необходимо (и если сделать его очень высоким, то рекомендуется). Это поможет сохранить ваши сортировки в памяти и не пролить их на диск (если это произойдет).

Чтобы получить реальную помощь, нам понадобится EXPLAIN ANALYZE , размещение его на веб-сайте объяснения.depesz.com может сделать его читабельным.

1 голос
/ 02 июля 2010

Чтобы предложить что-либо, вы должны опубликовать план выполнения запроса.

И "OMG Ponies" прав: ограничение 100 ограничит общий результат до 100 строк, оно не будет работать в отдельных группах!

В вики Postgres есть хорошая статья, в которой объясняется, как разместить вопрос, связанный с медленным запросом:

http://wiki.postgresql.org/wiki/SlowQueryQuestions

...