Yo uso PostgreSQL 9.1 en Ubuntu 12.04.
Necesito seleccionar registros dentro de un rango de tiempo: mi tabla time_limits
tiene dos timestamp
campos y una integer
propiedad. Hay columnas adicionales en mi tabla real que no están involucradas con 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 tabla contiene aproximadamente 2 millones de registros.
Consultas como las siguientes tomaron enormes cantidades de tiempo:
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';
Así que intenté agregar otro índice, el inverso de la PK:
create index idx_inversed on time_limits(id_phi, start_date_time, end_date_time);
Tengo la impresión de que el rendimiento mejoró: el tiempo para acceder a los registros en el medio de la tabla parece ser más razonable: entre 40 y 90 segundos.
Pero todavía son varias decenas de segundos para valores en el medio del rango de tiempo. Y dos veces más al apuntar al final de la tabla (cronológicamente hablando).
Intenté explain analyze
por primera vez obtener este plan 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
Ver los resultados en depesz.com.
¿Qué puedo hacer para optimizar la búsqueda? Puede ver todo el tiempo dedicado a escanear las dos columnas de marcas de tiempo una vez que id_phi
se establece en 0
. Y no entiendo el gran escaneo (¡60K filas!) En las marcas de tiempo. ¿No están indexados por la clave principal y idx_inversed
agregué?
¿Debo cambiar de tipos de marca de tiempo a otra cosa?
He leído un poco sobre los índices GIST y GIN. Supongo que pueden ser más eficientes en ciertas condiciones para tipos personalizados. ¿Es una opción viable para mi caso de uso?
explain analyze
salida es el tiempo que la consulta necesitó en el servidor . Si su consulta tarda 45 segundos, el tiempo adicional se gasta transfiriendo los datos de la base de datos al programa que ejecuta la consulta Después de todo, son 62682 filas y si cada fila es grande (por ejemplo, larga varchar
o text
columnas), esto puede afectar el tiempo de transferencia drásticamente
rows=62682 rows
es la estimación del planificador . La consulta devuelve 0 filas. (actual time=44.446..44.446 rows=0 loops=1)