我们有一张每月有大约10亿条记录的表。考虑到18个月的历史,我们正在谈论180亿条记录。按日期优化的PostgreSQL分区查询
该表按日期分区(所以我们有大约74个分区)。
对于我们的一个查询,我们需要获取一个给定单位的最后1000条记录。这样
SELECT code, obs_time
FROM unit_position
WHERE unit_id = 1
ORDER BY obs_time DESC LIMIT 1000;
问题的东西是对于这一点,我们在下面的结果说明:
限制(成本= 96181.06..96181.09行= 10宽度= 12)
- >排序(成本= 96181.06..102157.96行= 2390760宽度= 12)
Sort Key: unit_position .obs_time -> Result (cost=0.00..44517.60 rows=2390760 width=12) -> Append (cost=0.00..44517.60 rows=2390760 width=12) -> Seq Scan on unit_position (cost=0.00..42336.00 rows=2273600 width=12) -> Seq Scan on unit_position_week350 unit_position (cost=0.00..21.60 rows=1160 width=12) -> ... (ALL OTHER PARTITIONS) ... -> Seq Scan on unit_position_week450 unit_position (cost=0.00..21.60 rows=1160 width=12)
在其他公顷第二,如果我们得到这样一个查询(限制查询到第一区间,我们可以得到1000条记录),我们可以>快2倍的结果:
SELECT fake, obs_time
FROM unit_position
WHERE unit_id = 1
AND obs_time >= NOW() - '7 weeks'::interval
ORDER BY obs_time DESC LIMIT 1000;
问题是,考虑到我们是通过obs_time订购,有没有办法让查询使用分区,只搜索需要的前n个分区?
在大多数情况下,结果将在最近的4个分区中(所以它只会搜索这4个分区),并且只有在极少数情况下才需要搜索所有分区。
如果在获得n个分区(按顺序)后发现1000个结果,它将不考虑剩余的分区(数十亿条记录被丢弃)。测试/解释显示PostgreSQL没有这样做。它实际上适用于所有分区(如果它没有得到WHERE状态,则将QUERY限制在PARTITIONS的约束范围内。是否有办法强制这样做?(例如在ORACLE中,可以向DB引擎提供关于如何执行一些查询,即使我也不知道是否对分区执行此操作)
手动执行每个分区的开销(给出间隔)会给我们带来最坏的结果(并且这样做我们实际上可能正在工作不分区,这将有更好有不同的表)。
任何其他建议?
在我的文字(问题)我已经谈论这个案件结束。这是我已经尝试的事情之一,我实际上得到最差的结果(不是最糟糕的,但最糟糕的)。 在你的答案中,你必须做完整的查询,因为你在主查询中有ORDER BY。就像你说的,你需要通过子查询来获得它,否则你会得到最糟糕的结果。 – RGPT
@RGPT不幸的是,你并没有更好的选择。正如我所说的,分区在Pg中有点原始,它有一些缺点和上升。 –