我假设您的意思是严格控制,而不是两个时间段的重叠(因为您有 OVERLAPS 运算符)。
我们先生成测试数据:
CREATE UNLOGGED TABLE books ("from", "to") AS
SELECT g.date::date, (g.date + random() * 100 * INTERVAL '1 day')::date
FROM generate_series('1980-01-01', '2016-12-31', INTERVAL '1 minute') g ("date");
SELECT 19460161
Time: 24783.529 ms
现在我看到了三个选择,但首先让我们创建我将使用的三个索引:
CREATE INDEX point_gist
ON books
USING gist (point(EXTRACT(EPOCH FROM "from"), EXTRACT(EPOCH FROM "to")));
CREATE INDEX
Time: 242062.079 ms
CREATE INDEX from_to_btree ON books USING btree ("from", "to");
CREATE INDEX
Time: 26107.162 ms
CREATE INDEX daterange_gist ON books USING gist (daterange("from", "to", '[]'));
CREATE INDEX
Time: 791420.184 ms
VACUUM ANALYZE books;
VACUUM
Time: 3000.284 ms
请不要依赖这些时间;每个查询只执行一次,因为它们的性能不是我主要关心的问题。 YMMV。
1。通常的 BETWEEN
EXPLAIN ANALYZE
SELECT *
FROM books
WHERE
"from" BETWEEN '2000-01-01' AND '2001-01-01'
AND
"to" BETWEEN '2000-01-01' AND '2001-01-01';
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------
Index Only Scan using from_to_btree on books (cost=0.44..14849.78 rows=16578 width=8) (actual time=0.033..79.268 rows=456512 loops=1)
Index Cond: (("from" >= '2000-01-01'::date) AND ("from" <= '2001-01-01'::date) AND ("to" >= '2000-01-01'::date) AND ("to" <= '2001-01-01'::date))
Heap Fetches: 0
Total runtime: 93.792 ms
(4 rows)
2。 9.2+ 类型,日期范围
EXPLAIN ANALYZE
SELECT *
FROM books
WHERE daterange("from", "to", '[]') <@ daterange(date '2000-01-01', date '2001-01-01', '[]');
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on books (cost=16350.89..109027.83 rows=437996 width=8) (actual time=175.644..212.508 rows=456512 loops=1)
Recheck Cond: (daterange("from", "to", '[]'::text) <@ '[2000-01-01,2001-01-02)'::daterange)
-> Bitmap Index Scan on daterange_gist (cost=0.00..16241.39 rows=437996 width=0) (actual time=175.277..175.277 rows=456512 loops=1)
Index Cond: (daterange("from", "to", '[]'::text) <@ '[2000-01-01,2001-01-02)'::daterange)
Total runtime: 226.568 ms
(5 rows)
3。几何类型和运算符滥用
EXPLAIN ANALYZE
SELECT *
FROM books
WHERE
point(EXTRACT(EPOCH FROM "from"), EXTRACT(EPOCH FROM "to"))
<@
box(
point(EXTRACT(EPOCH FROM date '2000-01-01'), EXTRACT(EPOCH FROM date '2000-01-01')),
point(EXTRACT(EPOCH FROM date '2001-01-01'), EXTRACT(EPOCH FROM date '2001-01-01'))
);
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on books (cost=959.25..47748.30 rows=19460 width=8) (actual time=97.305..147.931 rows=456512 loops=1)
Recheck Cond: (point(date_part('epoch'::text, ("from")::timestamp without time zone), date_part('epoch'::text, ("to")::timestamp without time zone)) <@ '(978307200,978307200),(946684800,946684800)'::box)
-> Bitmap Index Scan on point_gist (cost=0.00..954.38 rows=19460 width=0) (actual time=96.926..96.926 rows=456512 loops=1)
Index Cond: (point(date_part('epoch'::text, ("from")::timestamp without time zone), date_part('epoch'::text, ("to")::timestamp without time zone)) <@ '(978307200,978307200),(946684800,946684800)'::box)
Total runtime: 161.947 ms
(5 rows)
这需要一点解释。因此,您通过提供 (x,y) 坐标来创建一个点,而通过提供两个点(对角)来创建一个框:((x1,y1),(x2,y2))。您可以看到该点包含在框(<@)中的要求意味着该点的 x 必须位于 x1 和 x2(含)之间,而该点的 y 必须位于 y1 和 y2(含)之间。