2010-07-01 8 views
5

Wysoki poziom: Czy mogę to zrobić order by, group by podstawie sum szybciej? (Str. 8,4, FWIW, na non-mały stolik .... myśleć O (miliony wierszy))poprawa algorytmu na proste wyglądających zapytania postgresql

Załóżmy miałem stół tak:

        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) 

a zapytanie chcę jest :

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; 

(angielski: top 100 pole1 pod adresem konkretnej (TS, kraj) gdzie 'Topness' jest sumą wyszukiwań dla każdego pasującego rzędu, niezależnie od wartości otherfield)

Czy istnieje cokolwiek Naprawdę mogę to przyspieszyć? Algorytmicznie wydaje się to być skanowaniem pełnoekranowym, ale być może czegoś mi brakuje.

+0

+1: Ładnie sformatowany i używa sekwencji do zapełnienia pliku! –

+1

'LIMIT 100' oznacza, że ​​zwracane jest tylko 100 wierszy, a nie 100 najlepszych dla każdego ts/kraju/etc. –

+0

Końcówka formatowania dla SO, pamiętaj, aby umieścić to wszystko małymi literami, o dziwo :) –

Odpowiedz

1

Aby móc zasugerować cokolwiek, należy opublikować plan wykonania kwerendy.

I "Kucyki OMG" mają rację: limit 100 ograniczy ogólny wynik do 100 rzędów, nie będzie działać na poszczególnych grupach!

Jest ładny artykuł w Postgres Wiki, która wyjaśnia, jak odpowiedzieć na pytanie związane z powolnym zapytania:

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

+0

Poprawiłem pytanie, aby odzwierciedlało punkt Kucyki OMG. Są poprawne, ale jest to właściwe zapytanie i to, czego chcę. Zaktualizowałem tekst, aby pasował. –

2

Każdy plan zapytania dla tego zapytania będzie musiał skanować każdy wiersz, który odpowiada WHERE warunki, zwijanie ich przez warunki grupowania - to znaczy ilość pracy jest proporcjonalna do liczby wierszy wejściowych do grupy przez, a nie liczba wierszy wyników.

Najbardziej efektywnym planem zapytania dla takiego zapytania jest pojedyncze skanowanie indeksu. Powinno to być możliwe, jeśli zbudujesz indeks (kraj, ts) w tej kolejności; z tym indeksem każde możliwe zapytanie tego formularza rozwiązuje ciągły zakres indeksu. Będzie to wymagało sortowania w pamięci - możliwe jest uniknięcie tego z innym indeksem.

Jak powiedzieli inni, opublikowanie planu wykonania jest najlepszym rozwiązaniem.

1

Indeks na (kraj, ts) jest najlepszym wyborem (jak sugeruje Nick Johnson), a dodatkowo możesz chcieć podnieść work_mem, jeśli nie jest on ustawiony wysoko. Możesz to ustawić w czasie rzeczywistym, jeśli jest to konieczne (i jeśli jest to bardzo wysokie, to zalecane). Pomoże to zachować twoje rodzaje w pamięci i nie rozleje się na dysk (jeśli tak się dzieje).

Aby uzyskać prawdziwą pomoc, musimy zobaczyć EXPLAIN ANALYZE, umieszczając ją na stronie explain.depesz.com, dzięki czemu będzie ona bardzo czytelna.