20

我正在编写一个概念验证应用程序,该应用程序旨在以每秒约 1000 条消息的速度获取实时点击流数据并将其写入 Amazon Redshift。

我正在努力获得与其他人声称的性能类似的东西(例如,here)。

我正在运行一个具有 2 个 dw.hs1.xlarge 节点(+ 领导者)的集群,并且执行负载的机器是与运行 64 位 Ubuntu 12.04.1 的 Redshift 集群位于同一 VPC 上的 EC2 m1.xlarge 实例。

我正在使用 Java 1.7(来自 Ubuntu 存储库的 openjdk-7-jdk)和 Postgresql 9.2-1002 驱动程序(主要是因为它是 Maven Central 中唯一让我的构建更容易的驱动程序!)。

我已经尝试了这里显示的所有技术,除了最后一个。

我不能使用COPY FROM,因为我们想“实时”加载数据,所以通过 S3 或 DynamoDB 暂存它并不是一个真正的选择,而且 RedshiftCOPY FROM stdin出于某种原因不支持。

这是我的日志的摘录,显示单个行以大约 15/秒的速度插入:

2013-05-10 15:05:06,937 [pool-1-thread-2] INFO  uk.co...redshift.DatabaseWriter - Beginning batch of 170
2013-05-10 15:05:18,707 [pool-1-thread-2] INFO  uk.co...redshift.DatabaseWriter - Done
2013-05-10 15:05:18,708 [pool-1-thread-2] INFO  uk.co...redshift.DatabaseWriter - Beginning batch of 712
2013-05-10 15:06:03,078 [pool-1-thread-2] INFO  uk.co...redshift.DatabaseWriter - Done
2013-05-10 15:06:03,078 [pool-1-thread-2] INFO  uk.co...redshift.DatabaseWriter - Beginning batch of 167
2013-05-10 15:06:14,381 [pool-1-thread-2] INFO  uk.co...redshift.DatabaseWriter - Done

我究竟做错了什么?我还可以采取哪些其他方法?

4

4 回答 4

22

Redshift(又名 ParAccel)是一个分析数据库。目标是使分析查询能够在大量数据中得到快速回答。为此,Redshift 以列格式存储数据。每列单独保存并针对列中的先前值进行压缩。这种压缩往往非常有效,因为给定的列通常包含许多重复和相似的数据。

这种存储方法在查询时提供了许多好处,因为只需要读取请求的列并且要读取的数据非常压缩。然而,这样做的代价是插入往往更慢并且需要更多的努力。此外,在表被 VACUUM 处理之前,未完全排序的插入可能会导致查询性能不佳。

因此,通过一次插入一行,您完全违背了 Redshift 的工作方式。数据库必须将您的数据连续附加到每一列并计算压缩。这有点像(但不完全是)向大量 zip 档案中添加单个值。此外,即使在插入数据之后,在运行 VACUUM 重新组织表之前,您仍然无法获得最佳性能。

如果您想“实时”分析您的数据,那么出于所有实际目的,您可能应该选择另一个数据库和/或方法。我的头顶是3:

  1. 接受“小”批处理窗口(5-15 分钟)并计划至少每天运行 VACUUM。
  2. 选择一个可以处理小插入的分析数据库(更多美元),例如 Vertica。
  3. 尝试使用允许单路径分析的“NoSQL”数据库,例如 Acunu Cassandra。
于 2013-05-20T12:40:29.603 回答
4

单次插入速度慢的原因是 Redshift 处理提交的方式。Redshift 有一个提交队列。

假设您插入第 1 行,然后提交 - 它进入红移提交队列以完成提交。

下一行,第 2 行,然后提交 - 再次进入提交队列。假设在此期间如果第 1 行的提交未完成,则第 2 行等待 1 的提交完成,然后开始处理第 2 行的提交。

因此,如果您批量插入,它会执行一次提交,并且比 Redshift 系统的单次提交更快。

您可以通过以下链接中的问题提示 #9:维护有效的数据加载获取提交队列信息。 https://aws.amazon.com/blogs/big-data/top-10-performance-tuning-techniques-for-amazon-redshift/

于 2018-03-19T04:26:06.930 回答
2

通过在同一个 INSERT 语句中将多个请求批处理在一起,我们已经能够在 Redshift 中每秒插入 1000 行(在我们的例子中,我们必须在每个 INSERT 中批处理约 200 个值元组)。如果您使用像 Hibernate 这样的 ORM 层,您可以将其配置为批处理(例如,参见http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/batch.html

于 2013-11-13T20:03:12.033 回答
1

通过批量写入每个事务 75,000 条记录的事务,我已经能够实现 2,400 次插入/秒。正如您所料,每条记录都很小,每条记录只有大约 300 个字节。

我正在查询安装在 EC2 实例上的 MariaDB,并将记录从安装 Maria 的同一 EC2 实例插入 RedShift。

更新

我修改了写入的方式,使其在 5 个并行线程中从 MariaDB 加载数据,并从每个线程写入 RedShift。这将性能提高到每秒 12,000 次以上的写入。

所以是的,如果你计划得当,你可以从 RedShift 写入中获得出色的性能。

于 2016-02-14T02:43:06.753 回答