【问题标题】:AWS Redshift JDBC insert performanceAWS Redshift JDBC 插入性能
【发布时间】:2013-05-05 07:47:55
【问题描述】:

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

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

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

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

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

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

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

【问题讨论】:

    标签: jdbc amazon-redshift


    【解决方案1】:

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

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

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

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

    1. 接受“小”批处理窗口(5-15 分钟)并计划至少每天运行一次 VACUUM。
    2. 选择一个可以处理小型插入的分析数据库(更多),例如 Vertica。
    3. 使用允许单路径分析的“NoSQL”数据库进行实验,例如 Acunu Cassandra。

    【讨论】:

    • 感谢您的回复。我理解你的所有观点,但这并不能真正解释为什么 10000 x 单行插入应该比从 S3 批量加载单个 10000 行 CSV 慢得多 - 我的意思是,压缩分析等仍然必须完成.请记住,我在这里不是在谈论 10000 笔交易。即使是具有 10000 次插入的单个事务也运行缓慢,Redshift 应该能够在这种情况下最大限度地减少块写入。
    • 除此之外,我们也不是在谈论几十个百分点的差异!我们谈论的是 15 行/秒,而我随后通过 S3 批量加载实现了 100,000 行/秒!
    • 不幸的是,这就是这种特殊野兽的本性。我不会假设包含在事务中的 10k 插入是批量处理的,特别是如果您说它没有更好的情况。我怀疑对于 Redshift,它要么是批量的,要么是逐行的。将 10k 写入 CSV 并批量加载以查看差异。
    • 正如我所提到的 - 从 S3 加载时,我已经看到高达 100k 行/秒。我很难相信有这么大的差异。我的意思是 - 如果您说我可以从 CSV/S3 执行 100k 行/秒,但通过 SQL INSERT 语句只能执行 20k/秒,我会对差异感到震惊。但是 100k 对 15 根本没有任何逻辑意义!
    • 顺便说一句,自从我回答这个问题以来,我一直在研究 SAP 的 HANA One 数据库,它实际上可能更适合您的场景。它可在 AWS Marketplace 上以高于实例成本 1 美元/小时的价格购买。在这种情况下有很多事情需要考虑,但如果你有时间的话,我至少会尝试一下。
    【解决方案2】:

    单次插入速度慢的原因是 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/

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 嗨@xpapad,你能分享一个链接,显示如何使用 Hibernate 和 Redshift 将记录插入数据库吗?我试图这样做,但合并和持久方法不起作用。事务正常结束,但没有插入记录。我可以使用手动插入查询来做到这一点,但我想使用 merge 和 persist 方法来做到这一点。
      • 你确定吗?这对我不起作用。使用 JDBC 批处理 API 似乎仍然具有单次插入的性能。您的意思是在单个 transaction 中有大量 INSERTS 帮助(我们已经观察到)?
      【解决方案4】:

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

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

      更新

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

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

      【讨论】:

      • 每秒 12k 的速度非常好!您能详细介绍一下您的解决方案吗?
      • 我赞同@inJakuzi 所说的话。提供解决方案详细信息,而不仅仅是您可以插入多快的指标。
      猜你喜欢
      • 1970-01-01
      • 2013-10-26
      • 2011-02-28
      • 1970-01-01
      • 2020-06-05
      • 1970-01-01
      • 2018-09-19
      相关资源
      最近更新 更多