2013-05-19 11 views
5

Mam tabela, która ma pole datetime "updated_at". Wiele moich zapytań będzie sprawdzać w tym polu za pomocą zapytań dotyczących zakresu, takich jak wiersze, które zaktualizowały> określoną datę.Postgres: Optymalizacja kwerend przez datetime

Już dodałem indeks do updated_at, ale większość moich zapytań jest nadal bardzo powolna, nawet gdy miałem limit liczby wierszy zwracanych.

Co jeszcze mogę zrobić, aby zoptymalizować zapytania, które wysyłają zapytania do pól datetime?

+5

Możesz pisać plan wyjaśnić całkowitą liczbę wierszy i dokładną wartość „bardzo wolno”? –

+0

Przeczytaj http://stackoverflow.com/tags/postgresql-performance/info (i powiązaną stronę wiki języka SlowQueryQuestions), a następnie zaktualizuj swoje pytanie za pomocą odpowiednich wyników "wyjaśnij analizę" i zgłoś ponownie. Ponieważ używasz generatora zapytań, możesz potrzebować użyć 'auto_explain' lub zalogować zapytania i ponownie wykonać je ręcznie. –

+0

Należy opublikować schemat i typ zapytania wolnego. Na pytanie, które jest sformułowane, nie można w uzasadniony sposób odpowiedzieć ... –

Odpowiedz

1

Zwykle optymalizatorzy baz danych nie zdecydują się używać indeksów dla otwartych zakresów, takich jak updated_at > somedate.

Ale w wielu przypadkach kolumna DATATIME nie przekroczy „teraz”, dzięki czemu można zachować semantyczne z > somedate przekształcając warunek do zakresie za pomocą between tak:

where updated_at between somedate and current_timestamp 

Predykat between znacznie częściej spowoduje, że optymalizator zdecyduje się użyć indeksu.


Prosimy o wpis o tym podejściu poprawić wydajność swoich kamieniołomów.

+2

Czy to naprawdę dotyczy PostgreSQL? Sądzę, że optymalizator powinien przyjrzeć się zakresowi wartości w odpowiedniej kolumnie, za pośrednictwem pg_statistics i wygenerować oszacowaną liczność zbioru wyników dla predykatu. Jeśli maksymalna wartość jest mniejsza lub równa wartości current_timestamp, nie sądzę, że byłaby duża różnica. Warto jednak przetestować Henley - plan wyjaśniający ujawni wszystko. –

+0

@DavidAldridge na moim doświadczeniu, '>' nie jest dobrze zoptymalizowany. Lubię też Harveya, by publikować wyniki. – Bohemian

+3

Postgres ** użyje ** indeksu dla '>' jeśli jest użyteczny. Nie ma potrzeby "między": Zobacz tutaj przykład http://sqlfiddle.com/#!12/e3142/3 Wszystko zależy - jak zwykle z indeksem - czy koszt korzystania z indeksu jest mniejszy niż coś innego –

0

Zakładając, że indeks jest używany, ale wydajność jest nadal słaba, jedynym lekarstwem mogę myśleć jest klaster tabelę według tego wskaźnika: http://www.postgresql.org/docs/9.1/static/sql-cluster.html

To przeniesie wierszy o tej samej wartości update_at być Współdzielone fizycznie, poprawiające wydajność zapytania, które uzyskuje dostęp do tej tabeli za pośrednictwem indeksu, szczególnie w przypadku skanowania o dużym zasięgu.

Należy jednak zwrócić uwagę na ostrzeżenia w dokumentacji i pamiętać, że w miarę aktualizacji wierszy klastrowanie nie jest zachowywane.

również:

Gdy stół jest skupione, dostęp EXCLUSIVE zamek nabywa się na nim. Zapobiega to działaniu innych operacji bazy danych (zarówno odczytów, jak i zapisów) w tabeli, dopóki CLUSTER nie zostanie ukończony.

W oparciu o te ograniczenia może nie być dobrym rozwiązaniem w Twojej sprawie, ale może być przydatne dla innych osób.

3

Dla danego zapytania, wykorzystanie wskaźnika zależy od kosztu przy użyciu tego wskaźnika w porównaniu do sekwencyjnego skanowania

Często deweloperzy myśleć, że ponieważ nie ma indeksu, zapytanie powinno działać szybciej, a jeśli zapytanie działa wolno, rozwiązaniem jest indeks. Zwykle ma to miejsce, gdy zapytanie zwróci kilka krotek. Jednak wraz ze wzrostem liczby krotek w wyniku może wzrosnąć koszt korzystania z indeksu.

Używasz PostgreSQL. Postgres nie obsługuje klastrowania wokół określonego atrybutu. Oznacza to, że postgres, w konfrontacji z zapytaniem o zakres (typu att> a i att < b), musi obliczyć liczbę krotek w wyniku (upewnij się, że odkurzasz często swoją bazę danych) i koszt użycia indeks w porównaniu do skanowania sekwencyjnego. wtedy zdecyduje, którą metodę zastosować.

można skontrolować tę decyzję uruchamiając

EXPLAIN ANALYZE <query>; 

w psql. Powie Ci, czy używa indeksu, czy nie.

Jeśli naprawdę chcesz używać indeksów zamiast skanowania sekwencyjnego (czasami jest to konieczne) i naprawdę wiesz, co robisz, możesz zmienić koszt skanowania sekwencyjnego w stałych terminarza lub wyłączyć sekwencyjne skanowanie na korzyść jakiejkolwiek innej metody. Zobacz tę stronę dla szczegółów:

http://www.postgresql.org/docs/9.1/static/runtime-config-query.html

Upewnij przeglądania prawidłową wersję dokumentacji.

--dmg