Używam PostgreSQL 9.1 na Ubuntu 12.04.
Muszę wybrać rekordy w określonym przedziale czasu: moja tabela time_limits
ma dwa timestamp
pola i jedną integer
właściwość. W mojej rzeczywistej tabeli znajdują się dodatkowe kolumny, które nie są związane z tym zapytaniem.
create table (
start_date_time timestamp,
end_date_time timestamp,
id_phi integer,
primary key(start_date_time, end_date_time,id_phi);
Ta tabela zawiera około 2 mln rekordów.
Zapytania takie jak poniższe zajmowały dużo czasu:
select * from time_limits as t
where t.id_phi=0
and t.start_date_time <= timestamp'2010-08-08 00:00:00'
and t.end_date_time >= timestamp'2010-08-08 00:05:00';
Próbowałem więc dodać kolejny indeks - odwrotność PK:
create index idx_inversed on time_limits(id_phi, start_date_time, end_date_time);
Mam wrażenie, że poprawiła się wydajność: Czas na dostęp do rekordów na środku tabeli wydaje się bardziej rozsądny: gdzieś pomiędzy 40 a 90 sekund.
Ale wciąż jest kilkadziesiąt sekund dla wartości w środku zakresu czasu. I jeszcze dwa razy, gdy celujesz w koniec tabeli (chronologicznie).
Po explain analyze
raz pierwszy próbowałem uzyskać ten plan zapytań:
Bitmap Heap Scan on time_limits (cost=4730.38..22465.32 rows=62682 width=36) (actual time=44.446..44.446 rows=0 loops=1)
Recheck Cond: ((id_phi = 0) AND (start_date_time <= '2011-08-08 00:00:00'::timestamp without time zone) AND (end_date_time >= '2011-08-08 00:05:00'::timestamp without time zone))
-> Bitmap Index Scan on idx_time_limits_phi_start_end (cost=0.00..4714.71 rows=62682 width=0) (actual time=44.437..44.437 rows=0 loops=1)
Index Cond: ((id_phi = 0) AND (start_date_time <= '2011-08-08 00:00:00'::timestamp without time zone) AND (end_date_time >= '2011-08-08 00:05:00'::timestamp without time zone))
Total runtime: 44.507 ms
Co mogę zrobić, aby zoptymalizować wyszukiwanie? Widać cały czas spędzony na skanowaniu dwóch kolumn znaczników czasu po id_phi
ustawieniu na 0
. I nie rozumiem dużego skanu (60 000 wierszy!) Znaczników czasu. Czy nie są one indeksowane według klucza podstawowego, a idx_inversed
ja dodałem?
Czy powinienem zmienić typy znaczników czasu na coś innego?
Przeczytałem trochę o indeksach GIST i GIN. Rozumiem, że mogą być bardziej wydajne w określonych warunkach dla niestandardowych typów. Czy jest to opłacalna opcja dla mojego przypadku użycia?
explain analyze
wyjściowych to czas potrzebny na zapytanie . Jeśli zapytanie zajmuje 45 sekund, dodatkowy czas spędzony jest na przesłaniu danych z bazy danych do programu uruchamiającego zapytanie. Po wszystkich 62682 wierszach i jeśli każdy wiersz jest duży (np. Ma długi varchar
lub text
kolumny), może to wpłynąć na czas przesyłania drastycznie.
rows=62682 rows
jest oszacowaniem planisty . Zapytanie zwraca 0 wierszy. (actual time=44.446..44.446 rows=0 loops=1)