Eu uso o PostgreSQL 9.1 no Ubuntu 12.04.
Preciso selecionar registros dentro de um intervalo de tempo: minha tabela time_limits
possui dois timestamp
campos e uma integer
propriedade. Existem colunas adicionais na minha tabela real que não estão envolvidas com esta consulta.
create table (
start_date_time timestamp,
end_date_time timestamp,
id_phi integer,
primary key(start_date_time, end_date_time,id_phi);
Esta tabela contém aproximadamente 2 milhões de registros.
Consultas como as seguintes levaram uma quantidade enorme de 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';
Então, tentei adicionar outro índice - o inverso do PK:
create index idx_inversed on time_limits(id_phi, start_date_time, end_date_time);
Tive a impressão de que o desempenho melhorou: o tempo para acessar registros no meio da tabela parece ser mais razoável: algo entre 40 e 90 segundos.
Mas ainda há várias dezenas de segundos para valores no meio do intervalo de tempo. E mais duas vezes ao mirar o final da tabela (cronologicamente falando).
Tentei explain analyze
pela primeira vez obter esse plano de consulta:
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
Veja os resultados em depesz.com.
O que eu poderia fazer para otimizar a pesquisa? Você pode ver todo o tempo gasto varrendo as duas colunas de carimbo de data / hora, uma vez id_phi
definido como 0
. E eu não entendo a grande varredura (60 mil linhas!) Nos registros de data e hora. Eles não são indexados pela chave primária e idx_inversed
eu adicionei?
Devo mudar de tipos de carimbo de data / hora para outra coisa?
Eu li um pouco sobre os índices GIST e GIN. Acho que eles podem ser mais eficientes em determinadas condições para tipos personalizados. É uma opção viável para o meu caso de uso?
explain analyze
saída é o tempo que a consulta precisava no servidor . Se a sua consulta demorar 45 segundos, o tempo adicional será gasto transferindo os dados do banco de dados para o programa que está executando a consulta. Afinal, são 62682 linhas e se cada linha é grande (por exemplo, possui longas varchar
ou text
colunas), isso pode afetar o tempo de transferência. drasticamente.
rows=62682 rows
é a estimativa do planejador . A consulta retorna 0 linhas. (actual time=44.446..44.446 rows=0 loops=1)