【发布时间】:2021-02-07 07:27:08
【问题描述】:
我试图弄清楚如何最有效地使用表分区和 tsrange 函数。我正在使用 PostgreSQL 13。
我将在此处发布一个示例,知道它效率不高并理解原因,但我正在寻找有关如何使其高效和调整的建议。 在下面的示例中,每次运行选择查询时都会读取所有分区。 我想查看预订日历中的游船行程是否与另一行程重叠。
CREATE TABLE boat_trips (
id INTEGER NOT NULL
, boat_name VARCHAR(32)
, departure_time TIMESTAMP WITHOUT TIME ZONE NOT NULL
, destination_time TIMESTAMP WITHOUT TIME ZONE NOT NULL
)
PARTITION BY RANGE (departure_time);
CREATE TABLE IF NOT EXISTS boat_trips_20210206 PARTITION OF boat_trips FOR VALUES FROM ('2021-02-06 00:00:00') TO ('2021-02-06 23:59:59');
CREATE TABLE IF NOT EXISTS boat_trips_20210207 PARTITION OF boat_trips FOR VALUES FROM ('2021-02-07 00:00:00') TO ('2021-02-07 23:59:59');
CREATE TABLE IF NOT EXISTS boat_trips_20210208 PARTITION OF boat_trips FOR VALUES FROM ('2021-02-08 00:00:00') TO ('2021-02-08 23:59:59');
INSERT INTO boat_trips VALUES (1, 'The Beautiful', '2021-02-06 11:15:00'::TIMESTAMP, '2021-02-06 12:15:00'::TIMESTAMP);
INSERT INTO boat_trips VALUES (2, 'The Incredible', '2021-02-06 13:15:00'::TIMESTAMP, '2021-02-06 14:15:00'::TIMESTAMP);
INSERT INTO boat_trips VALUES (3, 'The Beautiful', '2021-02-06 12:30:00'::TIMESTAMP, '2021-02-06 13:15:00'::TIMESTAMP);
INSERT INTO boat_trips VALUES (4, 'The Beautiful', '2021-02-07 11:15:00'::TIMESTAMP, '2021-02-07 12:15:00'::TIMESTAMP);
INSERT INTO boat_trips VALUES (5, 'The Incredible', '2021-02-07 13:15:00'::TIMESTAMP, '2021-02-07 14:15:00'::TIMESTAMP);
INSERT INTO boat_trips VALUES (6, 'The Beautiful', '2021-02-07 12:30:00'::TIMESTAMP, '2021-02-07 13:15:00'::TIMESTAMP);
INSERT INTO boat_trips VALUES (7, 'The Beautiful', '2021-02-08 11:15:00'::TIMESTAMP, '2021-02-08 12:15:00'::TIMESTAMP);
INSERT INTO boat_trips VALUES (8, 'The Incredible', '2021-02-08 13:15:00'::TIMESTAMP, '2021-02-08 14:15:00'::TIMESTAMP);
INSERT INTO boat_trips VALUES (9, 'The Beautiful', '2021-02-08 12:30:00'::TIMESTAMP, '2021-02-08 13:15:00'::TIMESTAMP);
然后我按如下方式运行选择查询:
SELECT DISTINCT bt.id, bt.boat_name, bt.departure_time, bt.destination_time
FROM boat_trips bt
WHERE tsrange(departure_time, destination_time) &&
tsrange '[2021-02-07 00:00:00,2021-02-08 00:00:00)';
如果我得到解释计划,我发现所有的分区都被解析了,这是正常的,因为分区键id是department_time。
如何在我的选择查询中利用分区和tsrange 函数?
我尝试在 tsrange(departure_time, destination_time) 上进行分区,它有效,但我找不到创建分区的语法。
这里有一个例子 => db fiddle
【问题讨论】:
-
为什么要实现分区?这主要不是性能问题,而是更多“数据管理”工具,例如快速删除旧行(通过删除分区而不是删除数百万行)。您希望该表中有多少行?为什么非分区表不能与 tsrange 上的索引一起使用?
-
这是因为在一天结束时,表将包含几百万行,并且查询主要是查询当天或将来的几天。但出于报告目的,我们需要保持历史可用。
-
“几百万行”不足以证明分区的合理性。如今,这被认为是一张小桌子。
-
我理解你的观点,你在某些方面是对的。我习惯于管理具有超过十亿行的表的数据库。这不是关于“我的比你的大”,而是还要考虑索引的大小并避免使用庞大索引的庞大表。分区不会受到伤害,尤其是对于相对“大”的表。顺便说一句,在讨论磁盘空间时,行数是无关紧要的。列的数量及其内容(blob?)呢?因此,我的示例针对该问题进行了简化。实际上,我不使用 3 根柱子和船 ;)
-
FOR VALUES FROM ('2021-02-06 00:00:00') TO ('2021-02-06 23:59:59');结束值应该与下一个分区的起始值相同,因为它是用
标签: sql postgresql partitioning