2010-02-10 10 views
10

Właśnie dokonałem restrukturyzacji bazy danych, aby korzystać z partitioning w Postgresie 8.2. Teraz mam problem z wydajnością zapytań:Wydajne sprawdzanie tablicy Postgres z wieloma partycjami

SELECT * 
FROM my_table 
WHERE time_stamp >= '2010-02-10' and time_stamp < '2010-02-11' 
ORDER BY id DESC 
LIMIT 100; 

Istnieje 45 milionów wierszy w tabeli. Przed przystąpieniem do partycjonowania używałby skanowania wstecznego indeksu i zatrzymania, gdy tylko osiągnie limit.

Po partycjonowaniu (w zakresach time_stamp), Postgres wykonuje pełne skanowanie indeksu tabeli głównej i odpowiedniej partycji i łączy wyniki, sortuje je, a następnie stosuje limit. To trwa zbyt długo.

mogę go naprawić z:

SELECT * FROM (
    SELECT * 
    FROM my_table_part_a 
    WHERE time_stamp >= '2010-02-10' and time_stamp < '2010-02-11' 
    ORDER BY id DESC 
    LIMIT 100) t 
UNION ALL 
SELECT * FROM (
    SELECT * 
    FROM my_table_part_b 
    WHERE time_stamp >= '2010-02-10' and time_stamp < '2010-02-11' 
    ORDER BY id DESC 
    LIMIT 100) t 
UNION ALL 
    ... and so on ... 
ORDER BY id DESC 
LIMIT 100 

ten przebiega szybko. Partycje, w których znaczniki czasu są poza zasięgiem, nie są nawet uwzględniane w planie zapytania.

Moje pytanie brzmi: czy jest jakaś podpowiedź lub składnia, której mogę użyć w Postgresie 8.2, aby uniemożliwić programowi planowania zapytań skanowanie pełnej tabeli, ale nadal używając prostej składni, która odnosi się tylko do tabeli głównej?

Zasadniczo, czy mogę uniknąć bólu związanego z dynamicznym budowaniem dużego zapytania UNION przez każdą z partycji, która ma być aktualnie zdefiniowana?

EDIT: Mam constraint_exclusion włączona (dzięki @Vinko Vrsalovic)

+1

8.2? naprawdę? Przed zrobieniem czegokolwiek, powinieneś rozważyć uaktualnienie do obsługiwanej (i aktualnej) wersji PostgreSQL (aktualna jest wersja 9.2). –

Odpowiedz

3

Czy próbowałeś Constraint wykluczenia (rozdział 5.9.4 w dokumencie już powiązany)

Ograniczenie wykluczenie jest technika optymalizacji poprawiająca wydajność dla tabel z partycjami zdefiniowanych w sposób opisany powyżej . Jako przykład:

SET constraint_exclusion = on; 
SELECT count(*) FROM measurement WHERE logdate >= DATE '2006-01-01'; 

bez więzów wykluczenia wyżej zapytania będzie skanować każdej z przegród Tablica pomiarów. Z włączonym ograniczeniem wykluczenie, planista będzie zbadania ograniczeń każdej partycji i starają się udowodnić, że partycja nie muszą być skanowane, ponieważ nie może zawierać żadnych wierszy spełniających gdzie klauzula kwerendy. Może to udowodnić osoba planująca , wykluczając partycję z planu kwerend.

Można użyć polecenia wytłumaczyć pokazać różnicę między planem z constraint_exclusion on i plan z go.

+0

Tak, włączono ograniczenie ograniczeń. Niestety, główna tabela (która jest zawsze pusta) jest zawsze uwzględniana w kwerendzie, ponieważ nie jest możliwe zastosowanie ograniczenia CHECK (przynajmniej w wersji 8.2). Oznacza to, że w kwerendzie są zawsze co najmniej dwie tabele –

4

Miałem podobny problem, który udało mi się naprawić, odrzucając warunki w GDZIE. EG: (zakładając kolumnę datownik jest timestamptz typ)

WHERE time_stamp >= '2010-02-10'::timestamptz and time_stamp < '2010-02-11'::timestamptz 

Ponadto, upewnij się, że stan sprawdzić w tabeli jest zdefiniowana w ten sam sposób ... EG: Check (datownik < '2010-02-10' :: timestamptz)

2

miałem ten sam problem i to sprowadza się do dwóch powodów w moim przypadku:

  1. miałem indeksowanej kolumnie typu timestamp WITH time zone i ograniczenie partycji o tę kolumnę z typem timestamp WITHOUT time zone.

  2. Po ustaleniu ograniczeń potrzebna była ANALYZE wszystkich tabel podrzędnych.

Edit: kolejny nieco wiedzy - ważne jest, aby pamiętać, że wyłączenie Ograniczenie (który pozwala PG pominąć skanowanie niektóre tabele w oparciu o kryteria zaborczych) nie działa z, cytuję: non-immutable function such as CURRENT_TIMESTAMP

Miałem żądania z CURRENT_DATE i było to częścią mojego problemu.

Powiązane problemy