Я використовую 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';
Тому я спробував додати ще один індекс - зворотний ПК:
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
. І я не розумію великого сканування (60К рядків!) На часових позначках. Чи не вони були індексовані первинним ключем, і idx_inversed
я додав?
Чи слід змінити типи часових позначок на щось інше?
Я трохи прочитав про GIST та GIN індекси. Я думаю, що вони можуть бути ефективнішими за певних умов для користувацьких типів. Це життєздатний варіант для мого випадку використання?
explain analyze
висновку, - це час запиту, необхідний на сервері . Якщо ваш запит займає 45 секунд, то додатковий час витрачається на передачу даних з бази даних до програми, яка виконує запит Зрештою, це 62682 рядки, і якщо кожен рядок великий (наприклад, має довгі varchar
або text
стовпці), це може вплинути на час передачі кардинально.
rows=62682 rows
планувальника . Запит повертає 0 рядків. (actual time=44.446..44.446 rows=0 loops=1)