Я использую PostgreSQL 9.1 на Ubuntu 12.04.
Мне нужно выбрать записи за определенный промежуток времени: в моей таблице time_limits
есть два timestamp
поля и одно integer
свойство. В моей фактической таблице есть дополнительные столбцы, которые не связаны с этим запросом.
create table (
start_date_time timestamp,
end_date_time timestamp,
id_phi integer,
primary key(start_date_time, end_date_time,id_phi);
Эта таблица содержит примерно 2 млн записей.
Такие запросы занимали огромное количество времени:
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';
Поэтому я попытался добавить еще один индекс - инверсию PK:
create index idx_inversed on time_limits(id_phi, start_date_time, end_date_time);
У меня сложилось впечатление, что производительность улучшилась: время доступа к записям в середине таблицы кажется более разумным: где-то между 40 и 90 секундами.
Но это все еще несколько десятков секунд для значений в середине временного диапазона. И еще вдвое больше при наведении на конец таблицы (в хронологическом порядке).
Я впервые попытался explain analyze
получить этот план запроса:
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
Смотрите результаты на depesz.com.
Что я могу сделать, чтобы оптимизировать поиск? Вы можете видеть, сколько времени тратится на сканирование двух столбцов меток времени, если для id_phi
них установлено значение 0
. И я не понимаю большого сканирования (60K строк!) На отметках времени. Разве они не проиндексированы по первичному ключу, а idx_inversed
я добавил?
Должен ли я изменить тип отметки времени на что-то другое?
Я немного читал об индексах GIST и GIN. Я считаю, что они могут быть более эффективными при определенных условиях для пользовательских типов. Это жизнеспособный вариант для моего варианта использования?
explain analyze
выходных данных, - это время, необходимое для запроса на сервере . Если ваш запрос занимает 45 секунд, то дополнительное время затрачивается на передачу данных из базы данных в программу, выполняющую запрос. В конце концов, это 62682 строки, и если каждая строка большая (например, имеет длину varchar
или text
столбцы), это может повлиять на время передачи коренным образом.
rows=62682 rows
планировщика . Запрос возвращает 0 строк. (actual time=44.446..44.446 rows=0 loops=1)