Uso PostgreSQL 9.1 su Ubuntu 12.04.
Devo selezionare i record in un intervallo di tempo: la mia tabella time_limits
ha due timestamp
campi e una integer
proprietà. Ci sono ulteriori colonne nella mia tabella reale che non sono coinvolte con questa query.
create table (
start_date_time timestamp,
end_date_time timestamp,
id_phi integer,
primary key(start_date_time, end_date_time,id_phi);
Questa tabella contiene circa 2 milioni di record.
Query come le seguenti hanno richiesto enormi quantità di tempo:
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';
Quindi ho provato ad aggiungere un altro indice - l'inverso del PK:
create index idx_inversed on time_limits(id_phi, start_date_time, end_date_time);
Ho avuto l'impressione che le prestazioni siano migliorate: il tempo per accedere ai record al centro della tabella sembra essere più ragionevole: tra 40 e 90 secondi.
Ma sono ancora diverse decine di secondi per i valori nell'intervallo di tempo. E altre due volte quando si prende di mira la fine del tavolo (in ordine cronologico).
Ho provato explain analyze
per la prima volta a ottenere questo piano di query:
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
Vedi i risultati su depesz.com.
Cosa potrei fare per ottimizzare la ricerca? Puoi vedere tutto il tempo trascorso scansionando le due colonne timestamp una volta id_phi
impostato su 0
. E non capisco la grande scansione (60K righe!) Sui timestamp. Non sono indicizzati dalla chiave primaria e idx_inversed
ho aggiunto?
Dovrei passare dai tipi di data e ora a qualcos'altro?
Ho letto qualcosa sugli indici GIST e GIN. Capisco che possono essere più efficienti a determinate condizioni per tipi personalizzati. È un'opzione praticabile per il mio caso d'uso?
explain analyze
nell'output è il tempo richiesto dalla query sul server . Se la query impiega 45 secondi, il tempo aggiuntivo viene impiegato per il trasferimento dei dati dal database al programma che esegue la query. Dopo tutto sono 62682 righe e se ogni riga è grande (ad esempio ha lunghe varchar
o text
colonne), ciò può influire sul tempo di trasferimento drasticamente.
rows=62682 rows
è la stima del pianificatore . La query restituisce 0 righe. (actual time=44.446..44.446 rows=0 loops=1)