19

我有一个问题,我需要非常快速地将大量数据(5+ 十亿行)加载到数据库中(理想情况下少于 30 分钟,但越快越好),最近有人建议我研究 postgresql(我用 mysql 失败了并且正在查看 hbase/cassandra)。我的设置是我有一个生成大量数据的集群(目前有 8 个服务器),我正在考虑在集群中的每台机器上本地运行数据库,它在本地快速写入,然后在最后(或在整个数据生成过程中)数据是合并在一起。数据没有任何顺序,所以我不在乎它在哪个特定的服务器上(只要它最终在那里)。

我的问题是,有没有什么好的教程或地方可以学习 PostgreSQL 自动分片(我发现像 sykpe 这样的公司在做自动分片但没有教程,我想自己玩这个)?我正在尝试做的事情可能吗?因为数据没有任何顺序,我打算使用自动递增的 ID 号,如果合并数据会导致冲突(这不再是一个大问题了)?

更新:下面弗兰克的想法消除了我所询问的自动递增冲突问题。现在的问题基本上是,我如何了解自动分片,它是否支持将数据分布式上传到多个服务器?

4

5 回答 5

14

第一:您真的需要将集群中生成的数据直接插入到关系数据库中吗?你不介意最后合并它,那么为什么还要插入数据库呢?在你的位置上,我会让你的集群节点编写平面文件,可能是 gzip 的 CSV 数据。然后,我将使用pg_bulkload 之类的工具批量导入和合并该数据。

如果您确实需要直接插入关系数据库:这就是 PgPool-II 和(尤其是)PgBouncer 的(部分用途。将 PgBouncer 配置为跨不同节点进行负载平衡,您应该已经很有序了。

请注意,PostgreSQL 是一个事务性数据库,具有强大的数据持久性保证。这也意味着,如果您以简单的方式使用它,执行大量小写入可能会很慢。您必须考虑您愿意在数据持久性、速度和硬件成本之间做出哪些权衡。

在一个极端情况下,每个都INSERT可以是自己的事务,在返回成功之前同步提交到磁盘。这将每秒事务的数量限制为磁盘子系统可以执行的 fsync() 数量,这通常只有每秒几十或几百次(没有电池备份 RAID 控制器)。如果你没有做任何特别的事情并且你没有将你INSERT的 s 包装在 aBEGIN和中,这是默认设置COMMIT

在另一个极端,您说“我真的不在乎我是否会丢失所有这些数据”并使用未记录的进行插入。如果它不能保证它是好的,这基本上给了数据库丢弃你的数据的权限 - 例如,在操作系统崩溃、数据库崩溃、断电等之后。

中间地带是你可能想要的地方。这涉及到异步提交组提交commit_delaycommit_siblings)、批处理插入到显式BEGIN和包装的组中的某种组合END。代替 INSERT 批处理,您可以COPY一次加载几千条记录。所有这些都以数据的持久性与速度为代价。

对于快速批量插入,您还应该考虑插入到除了主键之外没有任何索引的表中。也许甚至不是。完成批量插入后创建索引。这将快得多。

于 2012-04-26T03:22:02.657 回答
2

以下是一些可能会有所帮助的事情:

  • 每台服务器上的数据库都应该有一个具有该服务器独特特征的小型元数据表。比如是哪个服务器;服务器可以按顺序编号。除了该表的内容之外,尝试使每台服务器上的架构尽可能相似可能是明智的。

  • 对于数十亿行,您将需要 bigint id(或 UUID 等)。使用 bigints,您可以为每个服务器分配一个大范围,并设置其顺序以使用它。例如,服务器 1 获得 1..1000000000000000,服务器 2 获得 1000000000000001 到 2000000000000000 等。

  • 如果数据是简单的数据点(例如每秒恰好从 10 台仪器读取的温度读数),您可以通过将其存储在带有列的表中(time timestamp, values double precision[])而不是更正确的表中来获得效率提升(time timestamp, instrument_id int, value double precision)。这是为了提高效率而进行的显式非规范化。(我在博客上讲述了我自己对这个方案的体验。)

于 2012-04-25T20:51:51.617 回答
2

使用citus进行 PostgreSQL 自动分片。这个链接也很有帮助。

于 2017-08-17T11:55:59.237 回答
1

抱歉,我手头没有教程,但这里有一个可能的解决方案的概要:

  • 将八分之一的数据加载到每台服务器上的 PG 实例中
  • 为了获得最佳加载速度,不要使用插入,而是使用COPY方法
  • 加载数据时,不要将八个数据库合二为一。相反,使用plProxy启动单个语句来一次查询所有数据库(或满足您查询的正确语句)

如前所述,密钥可能是一个问题。使用不重叠的序列或 uuid 或带有字符串前缀的序列号,应该不难解决。

您应该从其中一台服务器上的 COPY 测试开始,看看您离 30 分钟的目标有多近。如果您的数据不重要并且您有最新的 Postgresql 版本,您可以尝试使用应该更快(但不是崩溃安全)的未记录表。听起来像一个有趣的项目,祝你好运。

于 2012-04-26T00:03:21.237 回答
-1

您可以使用 mySQL - 它支持跨集群的自动分片。

于 2014-07-01T19:09:37.283 回答