web-dev-qa-db-ja.com

AWS RedshiftJDBC挿入のパフォーマンス

ライブクリックストリームデータを毎秒約1000メッセージの速度で取得し、AmazonRedshiftに書き込むことを目的とした概念実証アプリを作成しています。

他の人が主張するパフォーマンスのようなものを手に入れるのに苦労しています(たとえば、 ここ )。

2 x dw.hs1.xlargeノード(+リーダー)でクラスターを実行しています。ロードを実行しているマシンは、64ビットUbuntu12.04.1を実行しているRedshiftクラスターと同じVPC上のEC2m1.xlargeインスタンスです。

Java 1.7(Ubuntuリポジトリのopenjdk-7-jdk)とPostgresql 9.2-1002ドライバーを使用しています(主に、Maven Centralでビルドが簡単になる唯一のドライバーだからです!)。

最後のテクニックを除いて、示されているすべてのテクニックを試しました ここ

「リアルタイム」でデータをロードしたいので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

私は何が間違っているのですか?他にどのようなアプローチを取ることができますか?

17
dty

Redshift(別名ParAccel)は分析データベースです。目標は、非常に大量のデータに対して分析クエリに迅速に回答できるようにすることです。そのために、Redshiftはデータを列形式で保存します。各列は個別に保持され、列の前の値に対して圧縮されます。特定の列は通常、多くの反復的で類似したデータを保持するため、この圧縮は非常に効果的である傾向があります。

このストレージアプローチは、要求された列のみを読み取る必要があり、読み取るデータが非常に圧縮されているため、クエリ時に多くの利点があります。ただし、このコストは、インサートが遅くなる傾向があり、はるかに多くの労力を必要とすることです。また、完全に順序付けされていない挿入は、テーブルがVACUUMされるまでクエリのパフォーマンスが低下する可能性があります。

したがって、一度に1つの行を挿入することで、Redshiftの動作方法に完全に反することになります。データベースは、データを各列に連続して追加し、圧縮を計算する必要があります。これは、多数のZipアーカイブに単一の値を追加するのと少し似ています(正確ではありません)。さらに、データが挿入された後でも、VACUUMを実行してテーブルを再編成するまで、最適なパフォーマンスは得られません。

データを「リアルタイム」で分析したい場合は、すべての実用的な目的で、おそらく別のデータベースやアプローチを選択する必要があります。ここに私の頭のてっぺんから3があります:

  1. 「小さな」バッチウィンドウ(5〜15分)を受け入れ、少なくとも毎日VACUUMを実行するように計画します。
  2. Verticaなどの小さな挿入に対応する分析データベース(より多くの$)を選択します。
  3. AcunuCassandraなどのシングルパス分析を可能にする「NoSQL」DBを試してみてください。
21
Joe Harris

同じINSERTステートメントで複数のリクエストをまとめてバッチ処理することで、Redshiftに1000行/秒を挿入することができました(この場合、各INSERTで最大200個の値タプルをバッチ処理する必要がありました)。 HibernateのようなORMレイヤーを使用する場合は、バッチ処理用に構成できます(たとえば、 http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/batch.html を参照してください)。 )

3
xpapad

単一の挿入が遅い理由は、Redshiftがコミットを処理する方法です。 Redshiftには、コミット用の単一のキューがあります。

行1を挿入してからコミットするとします。これは、redshiftコミットキューに移動してコミットを終了します。

次の行、行2、次にコミット-再びコミットキューに移動します。この間に、行1のコミットが完了していない場合、行2は1のコミットが完了するのを待ってから、行2のコミットの作業を開始します。

したがって、挿入をバッチ処理すると、単一のコミットが実行され、Redshiftシステムへの単一のコミットよりも高速になります。

以下のリンクの問題#8からコミットキュー情報を取得できます。 https://aws.Amazon.com/blogs/big-data/top-10-performance-tuning-techniques-for-Amazon-redshift/

1
scorpio155

トランザクションあたり75,000レコードのトランザクションに書き込みをバッチ処理することで、2,400回/秒の挿入を達成することができました。ご想像のとおり、各レコードは小さく、レコードあたり約300バイトです。

EC2インスタンスにインストールされているMariaDBにクエリを実行し、Mariaがインストールされているのと同じEC2インスタンスからRedShiftにレコードを挿入しています。

[〜#〜]更新[〜#〜]

5つの並列スレッドでMariaDBからデータをロードし、各スレッドからRedShiftに書き込むように、書き込みの方法を変更しました。これにより、パフォーマンスが12,000回以上の書き込み/秒に向上しました。

そうですね、正しく計画すれば、RedShiftの書き込みから優れたパフォーマンスを得ることができます。

0
Jonathan Leger