Подтвердить что ты не робот

Выберите записи из postgres, где временная метка находится в определенном диапазоне

У меня есть столбец прибытия типа timestamp в резервировании таблиц (я использую postgres). Как я могу выбрать все даты в этом году, например?

Я знаю, что могу сделать что-то вроде этого:

select * FROM reservations WHERE extract(year from arrival) = 2012;

Но я выполнил анализ, и похоже, что он требует сканирования последовательности. Есть ли лучший вариант?

P.S. 1 Хм. оба пути, кажется, требуют seq. сканирования. Но тот, который у wildplasser производит результаты быстрее - почему?

cmm=# EXPLAIN ANALYZE select * FROM reservations WHERE extract(year from arrival) = 2010;
                                                  QUERY PLAN                                                   
---------------------------------------------------------------------------------------------------------------
 Seq Scan on vrreservations  (cost=0.00..165.78 rows=14 width=4960) (actual time=0.213..4.509 rows=49 loops=1)
   Filter: (date_part('year'::text, arrival) = 2010::double precision)
 Total runtime: 5.615 ms
(3 rows)

cmm=# EXPLAIN ANALYZE SELECT * from reservations WHERE arrival > '2010-01-01 00:00:00' AND arrival < '2011-01-01 00:00:00';
                                                                  QUERY PLAN                                                                   
-----------------------------------------------------------------------------------------------------------------------------------------------
 Seq Scan on reservations  (cost=0.00..165.78 rows=51 width=4960) (actual time=0.126..2.491 rows=49 loops=1)
   Filter: ((arrival > '2010-01-01 00:00:00'::timestamp without time zone) AND (arrival < '2011-01-01 00:00:00'::timestamp without time zone))
 Total runtime: 3.144 ms
(3 rows)

** P.S. 2 - После того, как я создал индекс по столбцу прибытия, второй способ стал еще быстрее - поскольку он выглядит как запрос использует индекс. Ключ - я думаю, я буду с этим знаком. **

                                                                       QUERY PLAN                                                                        
---------------------------------------------------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on reservations  (cost=4.77..101.27 rows=51 width=4960) (actual time=0.359..0.791 rows=49 loops=1)
   Recheck Cond: ((arrival > '2010-01-01 00:00:00'::timestamp without time zone) AND (arrival < '2011-01-01 00:00:00'::timestamp without time zone))
   ->  Bitmap Index Scan on arrival_idx  (cost=0.00..4.76 rows=51 width=0) (actual time=0.177..0.177 rows=49 loops=1)
         Index Cond: ((arrival > '2010-01-01 00:00:00'::timestamp without time zone) AND (arrival < '2011-01-01 00:00:00'::timestamp without time zone))
 Total runtime: 1.265 ms
4b9b3361

Ответ 1

SELECT * 
FROM reservations 
WHERE arrival >= '2012-01-01'
AND arrival < '2013-01-01'
   ;

BTW, если распределение значений указывает на то, что сканирование индекса не будет стоить (например, если все значения указаны в 2012 году), оптимизатор все равно может выбрать полное сканирование таблицы. YMMV. Объясните, твой друг.

Ответ 2

Еще одна возможность сделать PostgreSQL индексом для вашего исходного запроса - создать индекс для используемого выражения:

create index arrival_year on reservations ( extract(year from arrival) );

Это откроет PostgreSQL с возможностью использования индекса для

select * 
FROM reservations 
WHERE extract(year from arrival) = 2012;

Обратите внимание, что выражение в индексе должно быть точно тем же выражением, которое используется в предложении where, чтобы сделать эту работу.