Postgresql Postgres分区?
我的软件每30分钟运行一次cronjob,它从谷歌分析/社交网络中提取数据,并将结果插入Postgres数据库 数据如下所示:Postgresql Postgres分区?,postgresql,database-partitioning,Postgresql,Database Partitioning,我的软件每30分钟运行一次cronjob,它从谷歌分析/社交网络中提取数据,并将结果插入Postgres数据库 数据如下所示: url text NOT NULL, rangeStart timestamp NOT NULL, rangeEnd timestamp NOT NULL, createdAt timestamp DEFAULT now() NOT NULL, ... (various integer columns) 因为一个查询返回10000多个项目,所以将这些数据存储在
url text NOT NULL,
rangeStart timestamp NOT NULL,
rangeEnd timestamp NOT NULL,
createdAt timestamp DEFAULT now() NOT NULL,
...
(various integer columns)
因为一个查询返回10000多个项目,所以将这些数据存储在一个表中显然不是一个好主意。按照这个速度,cronjob将每天生成约48万条记录,每月生成约1450万条记录
我认为解决方案应该使用几个表,例如,我可以使用一个特定的表来存储给定月份生成的数据:stats_2015_09、stats_2015_10、stats_2015_11等等
我知道Postgres支持表分区。然而,我对这个概念还不熟悉,所以我不确定什么是最好的方法。在这种情况下,我需要分区,还是应该手动创建这些表?或者有更好的解决办法
稍后将以各种方式查询数据,这些查询将运行得很快
编辑:
如果我最终得到12-14个表,每个表存储1000-2000万行,Postgres应该仍然能够快速运行select语句,对吗?插入不必非常快。对于注释来说,这太长了 在各种情况下,分区是一个好主意。我想到的两个问题是:
- 您的查询有一个
子句,可以很容易地映射到一个或几个分区上WHERE
- 您需要一种快速删除历史数据的方法(删除分区比删除记录快)
- 表中不能有外键引用
- 跨越多个表的查询很麻烦,因此很难回答简单的问题
- 维护表变成了一场噩梦(添加/删除列)
- 如果用户具有不同的角色,则必须仔细维护权限
在任何情况下,都应该从Postgres关于分区的文档开始,这就是。我应该注意到,Postgres的实现比其他数据库中的实现要困难一些,因此您可能需要查看MySQL或SQL Server的文档,了解它在做什么。首先,我想质疑您问题的前提: 因为一个查询返回10000多个项目,所以将这些数据存储在一个表中显然不是一个好主意 据我所知,没有根本原因说明数据库不能很好地处理一个包含数百万行的表。在极端情况下,如果您创建了一个没有索引的表,并且只是在表中添加行,则Postgres可以继续将这些行写入磁盘,直到存储空间用完为止。(我不确定内部可能还有其他限制;但如果是这样的话,那就太大了。) 只有当你试图用这些数据做一些事情时,问题才会出现,而确切的问题——因此也就是确切的解决方案——取决于你做了什么 如果要定期删除在固定时间之前插入的所有行,可以对
createdAt
列上的数据进行分区。然后,DELETE
将成为一个非常有效的DROP TABLE
,所有的INSERT
都将通过触发器路由到“当前”分区(如果导入脚本知道分区命名方案,甚至可以绕过它)<但是,code>SELECTs可能无法在其WHERE
子句中指定createAt
值的范围,因此需要查询所有分区并合并结果。一次保留的分区越多,效率就越低
或者,您可以检查表上的工作负载,并查看所有查询是否已经显式地声明了rangeStart
值。在这种情况下,您可以在rangeStart
上进行分区,并且在规划每个SELECT
查询时,查询规划器将能够消除除一个或几个分区以外的所有分区<代码>插入s需要通过触发器路由到相应的表,而维护操作(例如删除不再需要的旧数据)的效率要低得多
或者,您可能知道,一旦rangeEnd
变得“太旧”,您将不再需要数据,并且可以获得两个好处:按rangeEnd
分区,确保所有SELECT
查询明确提及rangeEnd
,并删除包含您不再感兴趣的数据的分区
借用git中Linus Torvald的术语,分区的“管道”是以表继承的形式构建到Postgres中的,但是除了手册中的示例之外,在“瓷器”方面几乎没有其他内容。然而,有一个非常好的方法,它提供了基于ID或日期范围管理分区集的功能;通过阅读文档了解不同的操作模式非常值得。在我的例子中,没有一个是完全匹配的,但是分叉扩展要比从头开始编写所有东西容易得多
请记住,分区并不是免费的,如果基于上述考虑因素,没有明显的候选列进行分区,那么实际上最好将数据保留在一个表中,并考虑其他优化策略。例如,部分索引(创建索引…其中
)可能能够处理最常查询的行子集;可能与“覆盖索引”相结合,Postgres可以直接从索引返回查询结果,而无需参考主表结构(“仅索引扫描”)。关于这个主题的内容很简洁,应该足够了。另请参见